1 Introduction

Keratoconus (KC) is the most common type of cornea dystrophia, having been shown that it usually includes, not besides structural but also enzymatic and proteomic changes. Also, there is an important mucosa surrounding the cornea, called the aqueous humor (AH) which is responsible for the transport of some vital metabolites that will serve as nutrients for the cornea. As such, it comes in handy studying its metabolic profile and learn about what, if any, changes might occur in the nutritional role of the aqueous humor towards cornea, and if there is any relationship between healthy humans and those with KC. Having this in mind, a set of investigators has conducted an approach to this issue by collecting samples from KC patients and healthy human beings, and done the proper proteomics analysis, which in the following case study, the NMR portion will be reviewed. Due to the hardness in obtaining samples from healthy, living patients, Snytnikova and collaborators chose to extract the “healthy” samples from cadavers to serve as a control group. This created an additional problem: the biochemical processes that partake in the post-mortem stage often alter the metabolic composition of aqueous humor (AH) which in turn will consequently also change cornea’s metabolome. In sum, this study has collected samples (both AH and KC) from 11 Keratoconus patients and 13 cadavers. The analytical data for quantification and identification of metabolites by NMR was done using a Bruker BioSpin and LC-MS.

The following data corresponds to the metabolic data from the NMR analysis and is accessible on MetaboLights through the codename MTBLS444 and it was processed using the help of Specmine. An R package which provides a set of methods for metabolomics data analysis, for example: data loading in different formats, pre-processing, metabolite identification, univariate and multivariate data analysis, machine learning, feature selection and pathway analysis.

3 Dataset Exploration

3.1 Dataset Download

Data was collected from the database MetaboLights (codename: MTBLS444) as aforementioned, loaded and read the NMR results in R with the following script:

## Dataset summary:
## Valid dataset
## Description:  Cornea - NMR 
## Type of data:  nmr-spectra 
## Number of samples:  44 
## Number of data points 14002 
## Number of metadata variables:  3 
## Number of missing values in data:  0 
## Mean of data values:  785938 
## Median of data values:  3714 
## Standard deviation:  22419219 
## Range of values:  -1412799 2.487e+09 
## Quantiles: 
##         0%        25%        50%        75%       100% 
##   -1412799     -19864       3714      31270 2487428460
## [1] 0

Summarization of data and further interpretation through the NMR spectra were conducted. The data has shown us 44 samples in concordance with the baseline paper, and no missing values.

After appropriate plotting and scale adjustment with definition of a threshold at 50000 we could roughly at a glance, identify that there is a clear difference between the data from the tissues and those with disease, as it would be expected.

Further cleanup of data was also partaken, in order to have a simplified, easier to work metadata. In this particular case, since normal tissues are all from cadavers and altered tissues from living patients, the variable “Human state” was removed from metadata.

3.2 Peak Calling

Following this process, peak detection was further partaken with the following code:

It was possible to detect 396 peaks and 13116 not assinged (NA) values.

All the peaks containing at least 66% NA values were removed and all of the remaining NA values were imputed a very small value, close to 0.

## [1] 100
## [1] 0

The analysis resulted in 100 peaks and 0 missing values.

3.3 Data Manipulation

The next step was to scale and organise our data, ensuring a normal distribution. This distribution is necessary in order for the statistical analysis to continue. Before the normalisation, the data was also scaled as follows:

The summary of scaled and normalised datasets can be seen bellow.

## Dataset summary:
## Valid dataset
## Description:  Cornea - NMR; Missing value imputation with method value; Scaling with method auto 
## Type of data:  nmr-peaks 
## Number of samples:  44 
## Number of data points 100 
## Number of metadata variables:  3 
## Number of missing values in data:  0 
## Mean of data values:  6.257e-18 
## Median of data values:  -0.4068 
## Standard deviation:  0.9887 
## Range of values:  -1.295 6.269 
## Quantiles: 
##      0%     25%     50%     75%    100% 
## -1.2954 -0.6341 -0.4068  0.3295  6.2694
## Dataset summary:
## Valid dataset
## Description:  Cornea - NMR; Missing value imputation with method value; Normalization with method median 
## Type of data:  nmr-peaks 
## Number of samples:  44 
## Number of data points 100 
## Number of metadata variables:  3 
## Number of missing values in data:  0 
## Mean of data values:  2.882e+11 
## Median of data values:  1 
## Standard deviation:  5.968e+12 
## Range of values:  5.126e-11 2.487e+14 
## Quantiles: 
##        0%       25%       50%       75%      100% 
## 5.126e-11 9.999e-01 1.000e+00 1.146e+01 2.487e+14

4 Univariate Statistical Analysis

4.1 Normality Test

In order to assess if our NMR data or peak intensity data follows a normal distribution, a Shapiro Test was performed to each sample with the following code:

## numeric(0)

Because of the test’s constraint on the number of values, it was performed with a random sample of 5000 intensity values for each sample. The test results indicate that none of our samples follow a normal distribution since all of the p-values are smaller than 0.05 by a very large degree.

This is to be expected because NMR data is characterized by many intensity peaks that often overlap along the ppm range. The presence of many intensity peaks makes it impossible for the full spectrum of our data to form a single normal distribution curve as it can be evidenced by the p-values in order of magnitude of e-94.

4.2 ANOVA

In order to determine which ppms have statistical differences in intensity peaks between different conditions, a Multi-factor ANOVA was performed.

For this analysis two factors were considered: the type of tissue and whether the person had KC or not. The Variance analysis was conducted with the assumption that the values of intensity were generated following a normal distribution.

Considering that multiple comparisons were conducted in ANOVA, a large set of inferences were made as well, so, to avoid erroneous inferences to occur, the Bonferroni correction to p-values was performed.

After the Bonferroni correction, a selection of the ppms whose previously calculated p-value was lower than 0.05 was conducted.

## [1] 24
## [1] 9
## [1] 12

The number of peaks presenting significant variance between tissues and whether had KC or not was 24 and 9 respectively.

5 Fold Change

Fold change was also performed to determine differences in intensity considering a specific condition as a reference.

For the fold change analysis, the reference conditions chosen were the absence of disease (control) and the cornea as a reference tissue.

As it can be seen in the plots, several peaks were related to over or under expression, regarding that some present fold changes above or below a threshold of twofold.

The peaks with at least 2-fold change were identified.

## [1] 60
## [1] 34

There are 60 peaks with significant fold change difference between tissues and 34 between the presence of KC.

The results from ANOVA and Fold Change were crossed in order to consistently identify peaks with differential intensity.

## [1] 21
## [1] 6

The resulting number of peaks filtered were 21 for differential intensity in tissues and 6 for the presence of KC.

Through the quick analysis of the first heatmap, it can be suggested that several ppms had lower intensities in samples of AH in comparison with the ones of the cornea. In the second heatmap, it can be seen a clear difference in intensities between the samples of patients with KC and others, since there is lower intensities associated with KC samples. Finally, looking at the last heatmap, it can be verified that for the samples of AH from KC patients (KeratAH) , the detection revealed lower intensities in comparison to the samples of the control’s AH (NormAH), whereas for 5.17, 6.04, 6.47 and 3.54 ppm the result was the contrary. For the other samples, the intensity values were apparantly similar.

6 Metabolite Identification

The identification of the metabolites in the dataset was obtained using Specmine, with the following code:

The experimental data was obtained using 1H-NMR 700 MHz at 25ºC, and Specmine does not have specific libraries for identification of 700 MHz NMR. This can lead to problems in the identification of metabolites present in the dataset.

A summary table of the identified HMDB IDs and corresponding ppms can be seen in the table above.

Filtering of the identified metabolites was performed, where only the ppms identified with differential expression were kept.

The HMDB IDs of the identified metabolites were converted to compound KEGG IDs with the following code.

After filtering the identified IDs, only 2 metabolites remain: Glycine, and Dihydrouracil. Glycine is a proteinogenic amino acid and Dihydrouracil is an intermediate in catabolism of Uracil.

7 Pathway Analysis

To analyse the pathways of the compounds involved in the dataset, we first obtained the organism code for Homo sapiens used in KEGG.

KEGG pathways ID’s are composed of 2 elements. The first is a prefix, composed entirely of letters representing the organism and a suffix representing the pathway.

We proceeded with the identification of the pathways from human metabolism that contain at least one of the metabolites identified as differentially expressed for all conditions.

Since the only metabolites identified are Dihydrouracil and Glycine, some of the identified pathways overlap.

7.1 Pyrimidine metabolism - hsa00240

7.2 Glycine, serine and threonine metabolism

7.3 Glutathione metabolism - hsa00480

Considering the NMR analysis done by Snytkova and cooperators (2017) and the previous filtering of data, Glycine is the only liable metabolite for further evaluation of pathways. Glycine is a major compound in vertebrates as it’s an important component in numerous processes in the central nervous system, and most importantly, in synaptic transportation. As such, it’s an important study target since its ability to mediate neuronal stimuli by aminoacid transport indicates a probable action in cortical-ocular interaction. After a thorough literature search on Glutathione (GSH) and Pyrimidine pathways, it was found that GSH has a significant variation in it’s concentration on brain tissues in a determined post mortem interval (PMI), indicating a major metabolic shift in this pathway. The identified brain cells with major variations in GSH were of the Cerebral Cortex and cerebellum, two main culprits for eye funcion in humans (Harish et al., 2011). As for pyrimidine synthesis. A 2015 study by Costa and her colleagues found that in a PMI of 2,6 to 24h, a significant increase in urea production was reported in human tissues, mainly in blood, with the exception of the ocular tissue Vitreous Humor, which in turn remains relatively stable. These results imply that a major change in metabolites maybe an influence in these results, mainly at the level of Glycine metabolism, through these pathways.

8 Enrichment Analysis

In order to obtain a better grasp of the possible enzymes and reactions altered in the different conditions, we performed a metabolite enrichment analysis using FELLA.

## General data:
## - KEGG graph:
##   * Nodes:  11011 
##   * Edges:  37087 
##   * Density:  0.0003059 
##   * Categories:
##     + pathway [316]
##     + module [189]
##     + enzyme [1133]
##     + reaction [5413]
##     + compound [3960]
##   * Size:  6.2 Mb 
## - KEGG names are ready.
## -----------------------------
## Hypergeometric test:
## - Matrix not loaded.
## -----------------------------
## Heat diffusion:
## - Matrix is ready
##   * Dim:  11011 x 3960 
##   * Size:  333.6 Mb 
## - RowSums are ready.
## -----------------------------
## PageRank:
## - Matrix not loaded.
## - RowSums not loaded.

First, the FELLA database was created, using only pathways identified previously and data from KEGG

We extracted the compound IDs for each condition.

We proceeded with the enrichment analysis using diffusing algorithms and normalisation through z-score.

## Writing diffusion results...
## Done.
## 87 nodes below the threshold have been limited to 15 nodes.

The top 15 enzymes and reactions enriched in these sets, ordered by p.score, can be seen in the table. Their relationship to each other and to Glycine and Dihydrouracil can be seen in the node graph.

9 PCA

In order to explore the relatedness of our samples we performed a PCA analysis.

In these results, the first 20 principal components have standard deviation greater than 1 (Kaiser criterion). These three components explain 90,11% of the variation in the data. The plot shows that the standard deviation starts to form a line with higher slope until the sixth component. This means that the first six PCs have more influence in the variability of the data. Nevertheless, the first 2 PCs are, without a doubt, the main influences in the data variability, since the standard deviation between them and the following ones is almost 1 unit.

We can use the proportion to determine which principal components explain most of the variability in the data. The higher the proportion, the more variability that the principal component explains. The size of the proportion can help to decide whether the principal component is important enough to retain. In the plot it is evident that the proportion value declines rapidly within the first three PCs. So, it can be stated that they are the most important ones.

The cumulative proportion is used to assess the total amount of variance that the consecutive principal components explain. Hence, as we can see, the first 20 PCs explain 90 % of the data variability, whereas almost 2/3 of the data variability is explained by the first 7 PCs.

## [1] 20

20 components that explain 90% of variability

As can be seen in the plot of the scores, there is a difference in the influence of the data related to the different samples and the two first components. In general, the samples of NormAH were positively correlated with PC1. Whereas the samples of Cornea were negatively correlated with both PC1 and PC2.

Finally, the samples of KeratAH (aqueous humor of patients with Keratoconus) were all positively correlated to PC2, achieving score values of 12.66 and 10.7.

Even though cornea samples revealed to be very similar concerning the correlation with both PCs, The scores related to samples of Aqueous Humor suggest a difference within samples extracted from humans in different conditions (with and without disease), similarly to what was suggested by the heatmaps generated previously.

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

The barplots above have the loadings for both PC1 and PC2 of the chemical shifts associated with the metabolites differentially expressed. As can be seen in the plots, the loading value related to 3.54 suggest that this variable strongly influence PC1, whereas the loading value for 3.43 suggest that this variable strongly influences PC2.

Since PC2 was positively correlated with the samples of KeratAH, the association between the metabolite related to the chemical shift of 3.43 (Dihydrouracil) and the disease seems plausible.

10 Clustering

Clustering analysis was subsequently done using both a hierarchical and a K-means algorithm since both can handle the amount of data on the samples, and results were further analysed.

10.2 K-means Clustering

##                
##                  1  2  3  4  5
##   Aqueous Humor  4  8  6  0  2
##   cornea         0  0  0  6 18
##              
##                1  2  3  4  5
##   Keratoconus  0  0  6  4  8
##   none         4  8  0  2 12

For the k means, data was also separated according to the condition, plotted and shown in two additional tables for better understanding on how the aggregation of data was done.

In sum, the tissues appear to be categorised in a somewhat similar way in both clustering algorithms. In a general overview, it appears that data is aggregated around their respective analysed conditions. Apart from a few discrepancies, distance data points towards a similarity relationship between normal corneas versus diseased ones, and the same applies to Aqueous Humor. Also, it is clear that diseased corneas and Aqueous Humor present themselves to be the most distant from each other. A plausible interpretation of these factors can be that the clear proximity of data from normal corneas and consequent distance between the diseased ones, and the fact that the same is applied for AH in both cases, suggest a difference in expression levels on these tissues, and their respectively state, being another evidence supporting the hypothesis that AH defficiently supplies corneas when affected with KC.

Yet another factor to consider would be the alive/deceased state, for this aggregation, although suggesting results closer to the ones expected, they don’t take in consideration the post-mortem processes on the metabolites of these tissues.

11 Machine Learning

11.1 Training models with all datasets using as final label the “Disease”

The number of samples was relatively low. For this reason, the prediction made by the model is not expected to be as accurate as it should be.

The best model representation was the random forest, since the associated accuracy was 95% (the higher value within all model representations).

## Leave-One-Out Cross-Validation Confusion Matrix 
## 
## (entries are percentual average cell counts across resamples)
##  
##              Reference
## Prediction    Keratoconus none
##   Keratoconus        36.4  0.0
##   none                4.5 59.1
##                             
##  Accuracy (average) : 0.9545

The most relevant features suggest that some metabolites might be important markers when it comes to predict whether a specific metabolic profile corresponds to post-mortem conditions (without the disease) or to humans with the disease. The metabolites identified were: Acetate (1.9 ppm), Methionine (2.12 ppm), Choline (3.18 ppm), Citrate (2.64 ppm) and Taurine (3.23 ppm).

11.2 Training models with part of the dataset with final label “Disease”

The best model representation was the random forest, since the associated accuracy was 94% (the higher value within all model representations).

##              
##               Keratoconus none
##   Keratoconus           3    1
##   none                  0    4

11.3 Training models with all dataset, using as final label the type of tissue

The model representation with the highest accuracy was naive_bayes.

## Leave-One-Out Cross-Validation Confusion Matrix 
## 
## (entries are percentual average cell counts across resamples)
##  
##                Reference
## Prediction      Aqueous Humor cornea
##   Aqueous Humor          43.2    0.0
##   cornea                  2.3   54.5
##                             
##  Accuracy (average) : 0.9773

The most relevant features were chemical shifts related to the following metabolites: Glycine (3.51 ppm), Valine (1.02 ppm), Lactate (4.1 ppm), Choline (3.18 pmm), Taurine (3.36 ppm), among others.

Since the experimental data was obtained using 1H-NMR 700 MHz at 25ºC, and Specmine does not have specific libraries for identification of 700 MHz NMR, the identification of this metabolites were performed resorting to fig. 1.

Representation of 1H-NMR results taken from Snytkova et al. (2017).

Representation of 1H-NMR results taken from Snytkova et al. (2017).

11.4 Training models with part of the dataset, using as final label the type of tissue

##                
##                 Aqueous Humor cornea
##   Aqueous Humor             3      0
##   cornea                    1      4

It was performed a train of the model with different types of model representation in order to figure out which one was the best for the construction of a model to predict whether the sample corresponds to AH, cornea, disease or its absence. The final label is the presence of disease or its absence, or if it belongs to AH or cornea sample. The validation method considered was the leave-one-out. Afterwards, a feature selection was conducted to filter the chemical shifts which were more relevant for the prediction.

As for the first 20 most important features selected, several chemical shifts were related to important metabolites associated to post mortem conditions and oxidative stress caused by the disease in cornea tissues.

For instance, acetate (1.9 ppm) and citrate (2.64 ppm) shown to be higher in corneas of KC patients, suggesting that oxidative stress might be related to higher concentrations of the aforementioned compounds. Moreover, post-mortem conditions such as the lack of oxygen causes the increase in concentration levels of lactate (4.1 ppm) in AH. (Donaldson and Lamount 2013, 2015; Zelentsova et.al 2016)

Other post-mortem conditions, in particular the lack of energy alters important cell mechanisms such as Na+ - K+ water pumps, increase osmotic pressure, leakage of metabolites, etc. These phenomena lead to a significant increase of post-mortem biomarkers concentration in AH. These biomarkers could be choline (3.18 ppm), taurine (3.36 ppm) and glycine (3.51 ppm). (Donaldson and Lamount 2013, 2014, 2015; Zelentsova et.al. 2016). These reports corroborate the feature selection results, since some of them were selected as relevant for training models in machine learning.

12 Conclusion

The present work has given us several insights into the metabolic profiles of Cornea and Aqueous Humor in Keratoconus patients and post-mortem samples (absence of disease).

Even though the identification process with specmine package was not reliable, it was still possible to roughly identify 2 metabolites differentially expressed. The identified metabolites were Glycine and Dihydrouracil.

Glycine was strongly correlated with PC1 in the PC Analysis which was also correlated with post-mortem conditions (NormKH samples). Futhermore, glycine-related pathway (Glutathione metabolism - hsa00480) and Dihydrouracil-related pathway (Pyrimidine metabolism - hsa00240) were likely associated with post-mortem biochemical processes.

The clustering analysis showed that the samples can be easily identified by their tissue but not as easily regarding their disease condition.

In order to effectively train the prediction models, a higher number of samples would be required. The feature selection results show that Acetate (1.9 ppm) and Citrate (2.65 ppm) are relevant features for the prediction of health status (presence or absence of KC). These results are compliant with the reported results in literature, given these compounds are reported as being related to oxidative stress in corneas (Buddi et al. 2002; Arnal et al. 2011; Wojcik et al. 2013, 2014; Karamichos et al. 2014; Shoham et al. 2008). Additionally, other metabolites were considered as relevant features for the prediction of tissue type. As reported in literature, these metabolites (Lactate, Glycine, Choline, Taurine, etc) are biomarkers for the estimation of post-mortem interval and tend to accumulate in Aqueous Humor due to post-mortem biochemical processes (Donaldson and Lamount 2013, 2014, 2015; Zelentsova et al. 2016). Thus, these features seem to be in line with previous reports, therefore they seem to be good to train models regarding the type of tissue and health status.

LS0tCnRpdGxlOiAiTVRCTFM0NDQ6IFF1YW50aXRhdGl2ZSBtZXRhYm9sb21pYyBhbmFseXNpcyBvZiB0aGUgaHVtYW4gY29ybmVhIGFuZCBhcXVlb3VzIGh1bW9yIgphdXRob3I6ICJKb8OjbyBDYXBlbGEgUEczODI3NCwgVGlhZ28gRmVycmVpcmEgUEczMzc2NSwgVGlhZ28gT2xpdmVpcmEgUEcyNDA5NiIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBkZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlIAogICAgdGhlbWU6IGZsYXRseSAKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93Ci0tLQpgYGB7ciBzZXR1cCwgY2FjaGUgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQpvcHRpb25zKHdpZHRoID0gMTUwLCBkaWdpdHMgPSA0KQprbml0cjo6b3B0c19jaHVuayRzZXQoYXV0b2RlcCA9IFRSVUUsIGNhY2hlID0gVFJVRSkKICNhdXRvbWF0aWNhbGx5IGNhY2hlIGFuZCBhc3NvY2lhdGUgb2JqZWN0cwoKIyBldmFsPUYgbmFvIGNvcnJlIG8gY29kaWdvIGRlbnRybyBkbyBjYW1wbwpgYGAgCgoKYGBgIHtyIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoIlJDdXJsIikKbGlicmFyeSgiS0VHR2dyYXBoIikKbGlicmFyeSgiRFQiKQpsaWJyYXJ5KCJzcGVjbWluZSIpCmxpYnJhcnkoIlJDeXRvc2NhcGUiKQpsaWJyYXJ5KCJHT3N0YXRzIikKbGlicmFyeSgiRkVMTEEiKQpsb2FkKCJwYXJ0ZTMuUkRhdGEiKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpLZXJhdG9jb251cyAoS0MpIGlzIHRoZSBtb3N0IGNvbW1vbiB0eXBlIG9mIGNvcm5lYSBkeXN0cm9waGlhLCBoYXZpbmcgYmVlbiBzaG93biB0aGF0IGl0IHVzdWFsbHkgaW5jbHVkZXMsIG5vdCBiZXNpZGVzIHN0cnVjdHVyYWwgYnV0IGFsc28gZW56eW1hdGljIGFuZCBwcm90ZW9taWMgY2hhbmdlcy4gQWxzbywgdGhlcmUgaXMgYW4gaW1wb3J0YW50IG11Y29zYSBzdXJyb3VuZGluZyB0aGUgY29ybmVhLCBjYWxsZWQgdGhlIGFxdWVvdXMgaHVtb3IgKEFIKSB3aGljaCBpcyByZXNwb25zaWJsZSBmb3IgdGhlIHRyYW5zcG9ydCBvZiBzb21lIHZpdGFsIG1ldGFib2xpdGVzIHRoYXQgd2lsbCBzZXJ2ZSBhcyBudXRyaWVudHMgZm9yIHRoZSBjb3JuZWEuIEFzIHN1Y2gsIGl0IGNvbWVzIGluIGhhbmR5IHN0dWR5aW5nIGl0cyBtZXRhYm9saWMgcHJvZmlsZSBhbmQgbGVhcm4gYWJvdXQgd2hhdCwgaWYgYW55LCBjaGFuZ2VzIG1pZ2h0IG9jY3VyIGluIHRoZSBudXRyaXRpb25hbCByb2xlIG9mIHRoZSBhcXVlb3VzIGh1bW9yIHRvd2FyZHMgY29ybmVhLCBhbmQgaWYgdGhlcmUgaXMgYW55IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhlYWx0aHkgaHVtYW5zIGFuZCB0aG9zZSB3aXRoIEtDLiBIYXZpbmcgdGhpcyBpbiBtaW5kLCBhIHNldCBvZiBpbnZlc3RpZ2F0b3JzIGhhcyBjb25kdWN0ZWQgYW4gYXBwcm9hY2ggdG8gdGhpcyBpc3N1ZSBieSBjb2xsZWN0aW5nIHNhbXBsZXMgZnJvbSBLQyBwYXRpZW50cyBhbmQgaGVhbHRoeSBodW1hbiBiZWluZ3MsIGFuZCBkb25lIHRoZSBwcm9wZXIgcHJvdGVvbWljcyBhbmFseXNpcywgd2hpY2ggaW4gdGhlIGZvbGxvd2luZyBjYXNlIHN0dWR5LCB0aGUgTk1SIHBvcnRpb24gd2lsbCBiZSByZXZpZXdlZC4gRHVlIHRvIHRoZSBoYXJkbmVzcyBpbiBvYnRhaW5pbmcgc2FtcGxlcyBmcm9tIGhlYWx0aHksIGxpdmluZyBwYXRpZW50cywgU255dG5pa292YSBhbmQgY29sbGFib3JhdG9ycyBjaG9zZSB0byBleHRyYWN0IHRoZSAiaGVhbHRoeSIgc2FtcGxlcyBmcm9tIGNhZGF2ZXJzIHRvIHNlcnZlIGFzIGEgY29udHJvbCBncm91cC4gVGhpcyBjcmVhdGVkIGFuIGFkZGl0aW9uYWwgcHJvYmxlbTogdGhlIGJpb2NoZW1pY2FsIHByb2Nlc3NlcyB0aGF0IHBhcnRha2UgaW4gdGhlIHBvc3QtbW9ydGVtIHN0YWdlIG9mdGVuIGFsdGVyIHRoZSBtZXRhYm9saWMgY29tcG9zaXRpb24gb2YgYXF1ZW91cyBodW1vciAoQUgpIHdoaWNoIGluIHR1cm4gd2lsbCBjb25zZXF1ZW50bHkgYWxzbyBjaGFuZ2UgY29ybmVhJ3MgbWV0YWJvbG9tZS4gCkluIHN1bSwgdGhpcyBzdHVkeSBoYXMgY29sbGVjdGVkIHNhbXBsZXMgKGJvdGggQUggYW5kIEtDKSBmcm9tIDExIEtlcmF0b2NvbnVzIHBhdGllbnRzIGFuZCAxMyBjYWRhdmVycy4gVGhlIGFuYWx5dGljYWwgZGF0YSBmb3IgcXVhbnRpZmljYXRpb24gYW5kIGlkZW50aWZpY2F0aW9uIG9mIG1ldGFib2xpdGVzIGJ5IE5NUiB3YXMgZG9uZSB1c2luZyBhIEJydWtlciBCaW9TcGluIGFuZCBMQy1NUy4KClRoZSBmb2xsb3dpbmcgZGF0YSBjb3JyZXNwb25kcyB0byB0aGUgbWV0YWJvbGljIGRhdGEgZnJvbSB0aGUgTk1SIGFuYWx5c2lzIGFuZCBpcyBhY2Nlc3NpYmxlIG9uIFtNZXRhYm9MaWdodHNdKGh0dHBzOi8vd3d3LmViaS5hYy51ay9tZXRhYm9saWdodHMvKSB0aHJvdWdoIHRoZSBjb2RlbmFtZSBNVEJMUzQ0NCBhbmQgaXQgd2FzIHByb2Nlc3NlZCB1c2luZyB0aGUgaGVscCBvZiBTcGVjbWluZS4gQW4gUiBwYWNrYWdlIHdoaWNoIHByb3ZpZGVzIGEgc2V0IG9mIG1ldGhvZHMgZm9yIG1ldGFib2xvbWljcyBkYXRhIGFuYWx5c2lzLCBmb3IgZXhhbXBsZTogZGF0YSBsb2FkaW5nIGluIGRpZmZlcmVudCBmb3JtYXRzLCBwcmUtcHJvY2Vzc2luZywgbWV0YWJvbGl0ZSBpZGVudGlmaWNhdGlvbiwgdW5pdmFyaWF0ZSBhbmQgbXVsdGl2YXJpYXRlIGRhdGEgYW5hbHlzaXMsIG1hY2hpbmUgbGVhcm5pbmcsIGZlYXR1cmUgc2VsZWN0aW9uIGFuZCBwYXRod2F5IGFuYWx5c2lzLiAKCiMgUGFja2FnZSBJbnN0YWxsYXRpb24KIyMgSW5zdGFsYXRpb24gb2YgUmVxdWlyZWQgUGFja2FnZXMKCmBgYHtyIFBhY2thZ2VzIGluc3RhbGF0aW9uLCBldmFsPUZ9CkJpb2NNYW5hZ2VyOjppbnN0YWxsKCJLRUdHZ3JhcGgiKQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiRkVMTEEiLCB2ZXJzaW9uID0gIjMuOCIpCkJpb2NNYW5hZ2VyOjppbnN0YWxsKCJSQ3lqcyIpCkJpb2NNYW5hZ2VyOjppbnN0YWxsKCJSQ3l0b3NjYXBlIikKQmlvY01hbmFnZXI6Omluc3RhbGwoIkdPc3RhdHMiKQpgYGAKCiMjIExvYWRpbmcgUmVxdWlyZWQgUGFja2FnZXMKCmBgYHtyIFBhY2thZ2VzIExvYWQsIGV2YWw9Rn0KbGlicmFyeSgiUkN1cmwiKQpsaWJyYXJ5KCJLRUdHZ3JhcGgiKQpsaWJyYXJ5KCJEVCIpCmxpYnJhcnkoInNwZWNtaW5lIikKbGlicmFyeSgiUkN5dG9zY2FwZSIpCmxpYnJhcnkoIkdPc3RhdHMiKQpsaWJyYXJ5KCJGRUxMQSIpCmBgYAoKCiMgRGF0YXNldCBFeHBsb3JhdGlvbgojIyBEYXRhc2V0IERvd25sb2FkCgpEYXRhIHdhcyBjb2xsZWN0ZWQgZnJvbSB0aGUgZGF0YWJhc2UgTWV0YWJvTGlnaHRzIChjb2RlbmFtZTogTVRCTFM0NDQpIGFzIGFmb3JlbWVudGlvbmVkLCBsb2FkZWQgYW5kIHJlYWQgdGhlIE5NUiByZXN1bHRzIGluIFIgd2l0aCB0aGUgZm9sbG93aW5nIHNjcmlwdDoKYGBge3IgRGF0YXNldCBMb2FkLCBldmFsPUZ9Ck1UQkxTNDQ0ID0gcmVhZF9CcnVrZXJfZmlsZXMoIk1UQkxTNDQ0LzEvZGF0YSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMubmFtZXMgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhX2ZpbGUgPSAiTVRCTFM0NDQvbWV0YWRhdGExLmNzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5oZWFkZXJfY29sID0gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5oZWFkZXJfcm93ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6aXBwZWQ9VCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb249IkNvcm5lYSAtIE5NUiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnggPSAicHBtIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwudmFsdWVzID0gImludGVuc2l0eSIpCmBgYAoKYGBge3IgRGF0YUZyYW1lIE1CTFM0NDR9CmFzLmRhdGEuZnJhbWUoTVRCTFM0NDQkZGF0YSkKYGBgCgoKCmBgYHtyIFN1bW1hcnkgTVRCTFM0NDR9CnN1bV9kYXRhc2V0KE1UQkxTNDQ0LCBzdGF0cz1UKSAjU3VtbWFyeSBvZiB0aGUgZGF0YXNldAoKY291bnRfbWlzc2luZ192YWx1ZXMoTVRCTFM0NDQpCmBgYAoKU3VtbWFyaXphdGlvbiBvZiBkYXRhIGFuZCBmdXJ0aGVyIGludGVycHJldGF0aW9uIHRocm91Z2ggdGhlIE5NUiBzcGVjdHJhIHdlcmUgY29uZHVjdGVkLiBUaGUgZGF0YSBoYXMgc2hvd24gdXMgNDQgc2FtcGxlcyBpbiBjb25jb3JkYW5jZSB3aXRoIHRoZSBiYXNlbGluZSBwYXBlciwgYW5kIG5vIG1pc3NpbmcgdmFsdWVzLgoKCmBgYHtyIFBsb3QgU3BlY3RyYSBNVEJMUzQ0NH0KcGFyKG1mcm93PWMoMiwyKSkgI1NwbGl0IGdyYXBoaWNhbCByZXByZXNlbnRhdGlvbnMgaW4gb25lIHNpbmdsZSB3aW5kb3cKCnBsb3Rfc3BlY3RyYShkYXRhc2V0ID0gTVRCTFM0NDQsIAogICAgICAgICAgICAgY29sdW1uLmNsYXNzID0gYygiVGlzc3VlIikpCmFibGluZShoID0gNTAwMDApCgpwbG90X3NwZWN0cmEoZGF0YXNldCA9IE1UQkxTNDQ0LCAKICAgICAgICAgICAgIGNvbHVtbi5jbGFzcyA9IGMoIlRpc3N1ZSIpLCAKICAgICAgICAgICAgIHlsaW09YygwLCA0ZTcpKQphYmxpbmUoaCA9IDUwMDAwKQoKcGxvdF9zcGVjdHJhKGRhdGFzZXQgPSBNVEJMUzQ0NCwgCiAgICAgICAgICAgICBjb2x1bW4uY2xhc3MgPSBjKCJEaXNlYXNlIikpCmFibGluZShoID0gNTAwMDApCgpwbG90X3NwZWN0cmEoZGF0YXNldCA9IE1UQkxTNDQ0LCAKICAgICAgICAgICAgIGNvbHVtbi5jbGFzcyA9IGMoIkRpc2Vhc2UiKSwgCiAgICAgICAgICAgICB5bGltPWMoMCwgNGU3KSkKYWJsaW5lKGggPSA1MDAwMCkKCm10ZXh0KHRleHQgPSAiU3BlY3RyYSBQbG90cyIsIAogICAgICBzaWRlID0gMywgCiAgICAgIG91dGVyID0gVCwgCiAgICAgIGxpbmUgPSAtMykKYGBgCgpBZnRlciBhcHByb3ByaWF0ZSBwbG90dGluZyBhbmQgc2NhbGUgYWRqdXN0bWVudCB3aXRoIGRlZmluaXRpb24gb2YgYSB0aHJlc2hvbGQgYXQgNTAwMDAgd2UgY291bGQgcm91Z2hseSBhdCBhIGdsYW5jZSwgaWRlbnRpZnkgdGhhdCB0aGVyZSBpcyBhIGNsZWFyIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZGF0YSBmcm9tIHRoZSB0aXNzdWVzIGFuZCB0aG9zZSB3aXRoIGRpc2Vhc2UsIGFzIGl0IHdvdWxkIGJlIGV4cGVjdGVkLgoKYGBge3IgTVRCTFM0NDQgQ2xlYW51cCwgZXZhbD1GfQpNVEJMUzQ0NF9DbGVhbiA9IHJlbW92ZV9tZXRhZGF0YV92YXJpYWJsZXMoTVRCTFM0NDQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGVzLnRvLnJlbW92ZSA9ICJIdW1hbiBzdGF0ZSIpCmBgYAoKRnVydGhlciBjbGVhbnVwIG9mIGRhdGEgd2FzIGFsc28gcGFydGFrZW4sIGluIG9yZGVyIHRvIGhhdmUgYSBzaW1wbGlmaWVkLCBlYXNpZXIgdG8gd29yayBtZXRhZGF0YS4gSW4gdGhpcyBwYXJ0aWN1bGFyIGNhc2UsIHNpbmNlIG5vcm1hbCB0aXNzdWVzIGFyZSBhbGwgZnJvbSBjYWRhdmVycyBhbmQgYWx0ZXJlZCB0aXNzdWVzIGZyb20gbGl2aW5nIHBhdGllbnRzLCB0aGUgdmFyaWFibGUgIkh1bWFuIHN0YXRlIiB3YXMgcmVtb3ZlZCBmcm9tIG1ldGFkYXRhLgoKCiMjIFBlYWsgQ2FsbGluZyAKCkZvbGxvd2luZyB0aGlzIHByb2Nlc3MsIHBlYWsgZGV0ZWN0aW9uIHdhcyBmdXJ0aGVyIHBhcnRha2VuIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlOiAKCmBgYHtyIFBlYWsgRGV0ZWN0aW9uLCBldmFsPUZ9Ck1UQkxTNDQ0X1BlYWtzID0gZGV0ZWN0X25tcl9wZWFrc19mcm9tX2RhdGFzZXQoZGF0YXNldCA9IE1UQkxTNDQ0KQpucm93KE1UQkxTNDQ0X1BlYWtzJGRhdGEpICNXaWxsIGRlcGljdCB0aGUgbnVtYmVyIG9mIHBlYWtzCmNvdW50X21pc3NpbmdfdmFsdWVzKE1UQkxTNDQ0X1BlYWtzKQpgYGAKCkl0IHdhcyBwb3NzaWJsZSB0byBkZXRlY3QgMzk2IHBlYWtzIGFuZCAxMzExNiBub3QgYXNzaW5nZWQgKE5BKSB2YWx1ZXMuIAoKYGBge3IgQ2xlYW4gTWlzc2luZyBWYWx1ZXMsIGV2YWw9Rn0KTVRCTFM0NDRfUGVha3NfQ2xlYW4gPSByZW1vdmVfdmFyaWFibGVzX2J5X25hcyhkYXRhc2V0ID0gTVRCTFM0NDRfUGVha3MsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5LnBlcmNlbnQgPSBULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5uYXMgPSA2NikgICNOQSB2YWx1ZSBmaWx0ZXJpbmcKCk1UQkxTNDQ0X1BlYWtzX0NsZWFuID0gbWlzc2luZ3ZhbHVlc19pbXB1dGF0aW9uKGRhdGFzZXQgPSBNVEJMUzQ0NF9QZWFrc19DbGVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDFlLTUpICNTdWJzdGl0dXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgd2l0aCBhIHZlcnkgc21hbGwgbnVtYmVyIApgYGAKCkFsbCB0aGUgcGVha3MgY29udGFpbmluZyBhdCBsZWFzdCA2NiUgTkEgdmFsdWVzIHdlcmUgcmVtb3ZlZCBhbmQgYWxsIG9mIHRoZSByZW1haW5pbmcgTkEgdmFsdWVzIHdlcmUgaW1wdXRlZCBhIHZlcnkgc21hbGwgdmFsdWUsIGNsb3NlIHRvIDAuCgpgYGB7ciBQZWFrIGlkIGZpbmFsIHN0YXRzfQpucm93KE1UQkxTNDQ0X1BlYWtzX0NsZWFuJGRhdGEpICNOdW1iZXIgb2YgcGVha3MgLSBhZnRlciBOQSByZW1vdmFsCmNvdW50X21pc3NpbmdfdmFsdWVzKE1UQkxTNDQ0X1BlYWtzX0NsZWFuKQpgYGAKClRoZSBhbmFseXNpcyByZXN1bHRlZCBpbiAxMDAgcGVha3MgYW5kIDAgbWlzc2luZyB2YWx1ZXMuCgoKIyMgRGF0YSBNYW5pcHVsYXRpb24KClRoZSBuZXh0IHN0ZXAgd2FzIHRvIHNjYWxlIGFuZCBvcmdhbmlzZSBvdXIgZGF0YSwgZW5zdXJpbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGlzIGRpc3RyaWJ1dGlvbiBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgZm9yIHRoZSBzdGF0aXN0aWNhbCBhbmFseXNpcyB0byBjb250aW51ZS4gQmVmb3JlIHRoZSBub3JtYWxpc2F0aW9uLCB0aGUgZGF0YSB3YXMgYWxzbyBzY2FsZWQgYXMgZm9sbG93czoKCmBgYHtyIE1UQkxTIERhdGEgTWFuaXB1bGF0aW9uLCBldmFsPUZ9Ck1UQkxTNDQ0X1NjYWxlZCA9IHNjYWxpbmcoZGF0YXNldCA9IE1UQkxTNDQ0X1BlYWtzX0NsZWFuLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiYXV0byIpCgpNVEJMUzQ0NF9Ob3JtYWxpemVkID0gbm9ybWFsaXplKGRhdGFzZXQgPSBNVEJMUzQ0NF9QZWFrc19DbGVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIm1lZGlhbiIpCmBgYAoKVGhlIHN1bW1hcnkgb2Ygc2NhbGVkIGFuZCBub3JtYWxpc2VkIGRhdGFzZXRzIGNhbiBiZSBzZWVuIGJlbGxvdy4KCmBgYHtyIFN1bSBEYXRhc2V0c30Kc3VtX2RhdGFzZXQoTVRCTFM0NDRfU2NhbGVkKQpzdW1fZGF0YXNldChNVEJMUzQ0NF9Ob3JtYWxpemVkKQpgYGAKCgojIFVuaXZhcmlhdGUgU3RhdGlzdGljYWwgQW5hbHlzaXMgCgojIyBOb3JtYWxpdHkgVGVzdAoKSW4gb3JkZXIgdG8gYXNzZXNzIGlmIG91ciBOTVIgZGF0YSBvciBwZWFrIGludGVuc2l0eSBkYXRhIGZvbGxvd3MgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCBhIFNoYXBpcm8gVGVzdCB3YXMgcGVyZm9ybWVkIHRvIGVhY2ggc2FtcGxlIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlOgoKYGBge3IgTm9ybWFsaXR5IHRlc3R9CmRpc3RfdGVzdF9kYXRhID0gYygpCmZvciAoc2FtcGxlbnIgaW4gYygxOjQ0KSkgewogIGRpc3RfdGVzdF9kYXRhID0gYyhkaXN0X3Rlc3RfZGF0YSwgc2hhcGlyby50ZXN0KHNhbXBsZShNVEJMUzQ0NCRkYXRhWyxzYW1wbGVucl0sIDUwMDApKSRwLnZhbHVlKQp9CgpkaXN0X3Rlc3QgPSBkYXRhLmZyYW1lKGRpc3RfdGVzdF9kYXRhKQpyb3duYW1lcyhkaXN0X3Rlc3QpID0gY29sbmFtZXMoTVRCTFM0NDQkZGF0YSkKY29sbmFtZXMoZGlzdF90ZXN0KSA9ICBjKCJwLXZhbHVlIERhdGEiKQpkaXN0X3Rlc3QKZGlzdF90ZXN0W2Rpc3RfdGVzdCA+PSAwLjA1XQpgYGAKCkJlY2F1c2Ugb2YgdGhlIHRlc3QncyBjb25zdHJhaW50IG9uIHRoZSBudW1iZXIgb2YgdmFsdWVzLCBpdCB3YXMgcGVyZm9ybWVkIHdpdGggYSByYW5kb20gc2FtcGxlIG9mIDUwMDAgaW50ZW5zaXR5IHZhbHVlcyBmb3IgZWFjaCBzYW1wbGUuClRoZSB0ZXN0IHJlc3VsdHMgaW5kaWNhdGUgdGhhdCBub25lIG9mIG91ciBzYW1wbGVzIGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24gc2luY2UgYWxsIG9mIHRoZSBwLXZhbHVlcyBhcmUgc21hbGxlciB0aGFuIDAuMDUgYnkgYSB2ZXJ5IGxhcmdlIGRlZ3JlZS4KClRoaXMgaXMgdG8gYmUgZXhwZWN0ZWQgYmVjYXVzZSBOTVIgZGF0YSBpcyBjaGFyYWN0ZXJpemVkIGJ5IG1hbnkgaW50ZW5zaXR5IHBlYWtzIHRoYXQgb2Z0ZW4gb3ZlcmxhcCBhbG9uZyB0aGUgcHBtIHJhbmdlLgpUaGUgcHJlc2VuY2Ugb2YgbWFueSBpbnRlbnNpdHkgcGVha3MgbWFrZXMgaXQgaW1wb3NzaWJsZSBmb3IgdGhlIGZ1bGwgc3BlY3RydW0gb2Ygb3VyIGRhdGEgdG8gZm9ybSBhIHNpbmdsZSBub3JtYWwgZGlzdHJpYnV0aW9uIGN1cnZlIGFzIGl0IGNhbiBiZSBldmlkZW5jZWQgYnkgdGhlIHAtdmFsdWVzIGluIG9yZGVyIG9mIG1hZ25pdHVkZSBvZiBlLTk0LgoKIyMgQU5PVkEKCkluIG9yZGVyIHRvIGRldGVybWluZSB3aGljaCBwcG1zIGhhdmUgc3RhdGlzdGljYWwgZGlmZmVyZW5jZXMgaW4gaW50ZW5zaXR5IHBlYWtzIGJldHdlZW4gZGlmZmVyZW50IGNvbmRpdGlvbnMsIGEgTXVsdGktZmFjdG9yIEFOT1ZBIHdhcyBwZXJmb3JtZWQuIAoKYGBge3IgQU5PVkEsIGV2YWw9Rn0KYW5vdmFfcmVzdWx0PW11bHRpZmFjdG9yX2Fvdl9hbGxfdmFycyhkYXRhc2V0ID0gTVRCTFM0NDRfU2NhbGVkLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEudmFycyA9IGMoIlRpc3N1ZSIsIkRpc2Vhc2UiKSwgIlRpc3N1ZSpEaXNlYXNlIikKcHZhbHVlc19hbm92YT1tdWx0aWZhY3Rvcl9hb3ZfcHZhbHVlc190YWJsZShhbm92YV9yZXN1bHQpCmBgYAoKRm9yIHRoaXMgYW5hbHlzaXMgdHdvIGZhY3RvcnMgd2VyZSBjb25zaWRlcmVkOiB0aGUgdHlwZSBvZiB0aXNzdWUgYW5kIHdoZXRoZXIgdGhlIHBlcnNvbiBoYWQgS0Mgb3Igbm90LiBUaGUgVmFyaWFuY2UgYW5hbHlzaXMgd2FzIGNvbmR1Y3RlZCB3aXRoIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIHZhbHVlcyBvZiBpbnRlbnNpdHkgd2VyZSBnZW5lcmF0ZWQgZm9sbG93aW5nIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCmBgYHtyIEJvbmZlcnJvbmkgQ29ycmVjdGlvbiwgZXZhbD1GfQphZGouYm9uZi50aXNzdWVzID0gcC5hZGp1c3QocHZhbHVlc19hbm92YSRUaXNzdWUsImJvbmZlcnJvbmkiKQphZGouYm9uZi5kaXNlYXNlPXAuYWRqdXN0KHB2YWx1ZXNfYW5vdmEkRGlzZWFzZSwiYm9uZmVycm9uaSIpCmFkai5ib25mLmludGVyYWN0aW9uPXAuYWRqdXN0KHB2YWx1ZXNfYW5vdmEkYFRpc3N1ZTpEaXNlYXNlYCwiYm9uZmVycm9uaSIpCgpwdmFsdWVzX2Fub3ZhJFRpc3N1ZT1hZGouYm9uZi50aXNzdWVzCnB2YWx1ZXNfYW5vdmEkRGlzZWFzZT1hZGouYm9uZi5kaXNlYXNlCnB2YWx1ZXNfYW5vdmEkYFRpc3N1ZTpEaXNlYXNlYD1hZGouYm9uZi5pbnRlcmFjdGlvbgpgYGAKCkNvbnNpZGVyaW5nIHRoYXQgbXVsdGlwbGUgY29tcGFyaXNvbnMgd2VyZSBjb25kdWN0ZWQgaW4gQU5PVkEsIGEgbGFyZ2Ugc2V0IG9mIGluZmVyZW5jZXMgd2VyZSBtYWRlIGFzIHdlbGwsIHNvLCB0byBhdm9pZCBlcnJvbmVvdXMgaW5mZXJlbmNlcyB0byBvY2N1ciwgdGhlIEJvbmZlcnJvbmkgY29ycmVjdGlvbiB0byBwLXZhbHVlcyB3YXMgcGVyZm9ybWVkLgoKYGBge3IgRmlsdHJhZ2VtIEFOT1ZBLCBldmFsPUZ9CmFub3ZhX3Rpc3N1ZXNfcHBtcz1yb3duYW1lcyhwdmFsdWVzX2Fub3ZhW3doaWNoKHB2YWx1ZXNfYW5vdmEkVGlzc3VlPDAuMDUpLF0pCmFub3ZhX2Rpc2Vhc2VfcHBtcz1yb3duYW1lcyhwdmFsdWVzX2Fub3ZhW3doaWNoKHB2YWx1ZXNfYW5vdmEkRGlzZWFzZTwwLjA1KSxdKQphbm92YV9pbnRlcmFjdGlvbl9wcG1zPXJvd25hbWVzKHB2YWx1ZXNfYW5vdmFbd2hpY2gocHZhbHVlc19hbm92YSRgVGlzc3VlOkRpc2Vhc2VgPDAuMDUpLF0pCmBgYAoKQWZ0ZXIgdGhlIEJvbmZlcnJvbmkgY29ycmVjdGlvbiwgYSBzZWxlY3Rpb24gb2YgdGhlIHBwbXMgd2hvc2UgcHJldmlvdXNseSBjYWxjdWxhdGVkIHAtdmFsdWUgd2FzIGxvd2VyIHRoYW4gMC4wNSB3YXMgY29uZHVjdGVkLgoKYGBge3IgTlIgZGUgcGljb3MgY29tIGRpZmVyZW5jYXMgZW0gQU5PVkF9Cmxlbmd0aChhbm92YV90aXNzdWVzX3BwbXMpCmxlbmd0aChhbm92YV9kaXNlYXNlX3BwbXMpCmxlbmd0aChhbm92YV9pbnRlcmFjdGlvbl9wcG1zKQpgYGAKClRoZSBudW1iZXIgb2YgcGVha3MgcHJlc2VudGluZyBzaWduaWZpY2FudCB2YXJpYW5jZSBiZXR3ZWVuIHRpc3N1ZXMgYW5kIHdoZXRoZXIgaGFkIEtDIG9yIG5vdCB3YXMgMjQgYW5kIDkgcmVzcGVjdGl2ZWx5LiAKCiMgRm9sZCBDaGFuZ2UKCkZvbGQgY2hhbmdlIHdhcyBhbHNvIHBlcmZvcm1lZCB0byBkZXRlcm1pbmUgZGlmZmVyZW5jZXMgaW4gaW50ZW5zaXR5IGNvbnNpZGVyaW5nIGEgc3BlY2lmaWMgY29uZGl0aW9uIGFzIGEgcmVmZXJlbmNlLiAKCmBgYHtyIEZvbGQgQ2hhbmdlLCBldmFsPUZ9CkRpc2Vhc2VfZm9sZGNoYW5nZSA9IGZvbGRfY2hhbmdlKGRhdGFzZXQgPSBNVEJMUzQ0NF9Ob3JtYWxpemVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YS52YXIgPSAiRGlzZWFzZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWYudmFsdWUgPSAibm9uZSIpCgpUaXNzdWVfZm9sZGNoYW5nZSA9IGZvbGRfY2hhbmdlKGRhdGFzZXQgPSBNVEJMUzQ0NF9Ob3JtYWxpemVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhLnZhciA9ICJUaXNzdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWYudmFsdWUgPSAiY29ybmVhIikKYGBgCgpGb3IgdGhlIGZvbGQgY2hhbmdlIGFuYWx5c2lzLCB0aGUgcmVmZXJlbmNlIGNvbmRpdGlvbnMgY2hvc2VuIHdlcmUgdGhlIGFic2VuY2Ugb2YgZGlzZWFzZSAoY29udHJvbCkgYW5kIHRoZSBjb3JuZWEgYXMgYSByZWZlcmVuY2UgdGlzc3VlLgoKYGBge3IgRm9sZCBDaGFuZ2UgUGxvdHN9CnBsb3RfZm9sZF9jaGFuZ2UoZGF0YXNldCA9IE1UQkxTNDQ0X05vcm1hbGl6ZWQsIAogICAgICAgICAgICAgICAgIGZjLnJlc3VsdHMgPSBEaXNlYXNlX2ZvbGRjaGFuZ2UsIAogICAgICAgICAgICAgICAgIGZjLnRocmVzaG9sZCA9IDIsIAogICAgICAgICAgICAgICAgIHhsYWIgPSAicHBtcyIpCm10ZXh0KHRleHQgPSAiRGlzZWFzZXMgS0MgRm9sZCBDaGFuZ2UiLCAKICAgICAgc2lkZSA9IDMsIAogICAgICBvdXRlciA9IFQsIAogICAgICBsaW5lID0gLTMpCgpwbG90X2ZvbGRfY2hhbmdlKGRhdGFzZXQgPSBNVEJMUzQ0NF9Ob3JtYWxpemVkLCAKICAgICAgICAgICAgICAgICBmYy5yZXN1bHRzID0gVGlzc3VlX2ZvbGRjaGFuZ2UsIAogICAgICAgICAgICAgICAgIGZjLnRocmVzaG9sZCA9IDIsIAogICAgICAgICAgICAgICAgIHhsYWIgPSAicHBtcyIpCm10ZXh0KHRleHQgPSAiVGlzc3VlIEZvbGQgQ2hhbmdlIiwKICAgICAgc2lkZSA9IDMsIAogICAgICBvdXRlciA9IFQsIAogICAgICBsaW5lID0gLTMpCmBgYAoKQXMgaXQgY2FuIGJlIHNlZW4gaW4gdGhlIHBsb3RzLCBzZXZlcmFsIHBlYWtzIHdlcmUgcmVsYXRlZCB0byBvdmVyIG9yIHVuZGVyIGV4cHJlc3Npb24sIHJlZ2FyZGluZyB0aGF0IHNvbWUgcHJlc2VudCBmb2xkIGNoYW5nZXMgYWJvdmUgb3IgYmVsb3cgYSB0aHJlc2hvbGQgb2YgdHdvZm9sZC4KCmBgYHtyIEZvbGQgY2hhbmdlIHBlYWtzLCBldmFsPUZ9CnBwbXNfZGlzZWFzZV9mb2xkY2hhbmdlPXJvd25hbWVzKERpc2Vhc2VfZm9sZGNoYW5nZVtEaXNlYXNlX2ZvbGRjaGFuZ2UkRm9sZENoYW5nZSA+IDIsIF0pCnBwbXNfdGlzc3VlX2ZvbGRjaGFuZ2U9cm93bmFtZXMoVGlzc3VlX2ZvbGRjaGFuZ2VbVGlzc3VlX2ZvbGRjaGFuZ2UkRm9sZENoYW5nZSA+IDIsIF0pCmBgYAoKVGhlIHBlYWtzIHdpdGggYXQgbGVhc3QgMi1mb2xkIGNoYW5nZSB3ZXJlIGlkZW50aWZpZWQuCgpgYGB7ciBOdW1iZXIgb2YgcGVha3MgaW4gZm9sZCBjaGFuZ2V9Cmxlbmd0aChwcG1zX3Rpc3N1ZV9mb2xkY2hhbmdlKQpsZW5ndGgocHBtc19kaXNlYXNlX2ZvbGRjaGFuZ2UpCmBgYAoKVGhlcmUgYXJlIDYwIHBlYWtzIHdpdGggc2lnbmlmaWNhbnQgZm9sZCBjaGFuZ2UgZGlmZmVyZW5jZSBiZXR3ZWVuIHRpc3N1ZXMgYW5kIDM0IGJldHdlZW4gdGhlIHByZXNlbmNlIG9mIEtDLgoKYGBge3IgQ3Jvc3MgQU5PVkEgd2l0aCBGb2xkIENoYW5nZSwgZXZhbD1GfQpjcm9zc19kaXNlYXNlPWMoKQpmb3IgKHBwbSBpbiBhbm92YV9kaXNlYXNlX3BwbXMpewogIGlmIChwcG0gJWluJSBwcG1zX2Rpc2Vhc2VfZm9sZGNoYW5nZSl7CiAgICBjcm9zc19kaXNlYXNlPWMoY3Jvc3NfZGlzZWFzZSxwcG0pCiAgfQp9CgpkYXRhX3Rpc3N1ZXNfbWV0YWJvbGl0ZXM9TVRCTFM0NDRfUGVha3NfQ2xlYW4kZGF0YVthcy52ZWN0b3IoY3Jvc3NfdGlzc3VlKSxdCgpjcm9zc190aXNzdWU9YygpCmZvciAocHBtIGluIGFub3ZhX3Rpc3N1ZXNfcHBtcyl7CiAgaWYgKHBwbSAlaW4lIHBwbXNfdGlzc3VlX2ZvbGRjaGFuZ2UpewogICAgY3Jvc3NfdGlzc3VlPWMoY3Jvc3NfdGlzc3VlLHBwbSkKICB9Cn0KCmRhdGFfZGlzZWFzZV9tZXRhYm9saXRlcz1NVEJMUzQ0NF9QZWFrc19DbGVhbiRkYXRhW2FzLnZlY3Rvcihjcm9zc19kaXNlYXNlKSxdCgpkYXRhX2ludGVyYWN0aW9uX21ldGFib2xpdGVzPU1UQkxTNDQ0X1BlYWtzX0NsZWFuJGRhdGFbYXMudmVjdG9yKGFub3ZhX2ludGVyYWN0aW9uX3BwbXMpLF0KYGBgCgpUaGUgcmVzdWx0cyBmcm9tIEFOT1ZBIGFuZCBGb2xkIENoYW5nZSB3ZXJlIGNyb3NzZWQgaW4gb3JkZXIgdG8gY29uc2lzdGVudGx5IGlkZW50aWZ5IHBlYWtzIHdpdGggZGlmZmVyZW50aWFsIGludGVuc2l0eS4KCmBgYHtyIE51bWJlciBvZiBwZWFrcyBjcm9zc2VkIGluIEFOT1ZBIGFuZCBGb2xkIENoYW5nZX0KbnJvdyhkYXRhX3Rpc3N1ZXNfbWV0YWJvbGl0ZXMpCm5yb3coZGF0YV9kaXNlYXNlX21ldGFib2xpdGVzKQpgYGAKClRoZSByZXN1bHRpbmcgbnVtYmVyIG9mIHBlYWtzIGZpbHRlcmVkIHdlcmUgMjEgZm9yIGRpZmZlcmVudGlhbCBpbnRlbnNpdHkgaW4gdGlzc3VlcyBhbmQgNiBmb3IgdGhlIHByZXNlbmNlIG9mIEtDLgoKYGBge3IgSGVhdG1hcHN9CmhlYXRtYXAoZGF0YV90aXNzdWVzX21ldGFib2xpdGVzLCAKICAgICAgICBtYWluPSJEaWZmZXJlbmNlcyBpbiBleHByZXNzaW9uIGJldHdlZW4gdGlzc3VlcyIsCiAgICAgICAgeGxhYj0iVHlwZSBvZiBzYW1wbGUiLAogICAgICAgIHlsYWI9InBwbSIpCgpoZWF0bWFwKGRhdGFfZGlzZWFzZV9tZXRhYm9saXRlcywKICAgICAgICBtYWluPSJEaWZmZXJlbmNlcyBpbiBleHByZXNzaW9uIGJldHdlZW4gZGlzZWFzZXMgKEtDIG9yIG5vbmUpIiwKICAgICAgICB4bGFiPSJUeXBlIG9mIHNhbXBsZSIsCiAgICAgICAgeWxhYj0icHBtIikKCmhlYXRtYXAoZGF0YV9pbnRlcmFjdGlvbl9tZXRhYm9saXRlcywKICAgICAgICBtYWluPSJEaWZmZXJlbmNlcyBpbiBleHByZXNzaW9uIHJlZ2FyZGluZyB0aGUgaW50ZXJhY3Rpb24gb2YgdGhlIGZhY3RvcnMiLAogICAgICAgIHhsYWI9IlR5cGUgb2Ygc2FtcGxlIiwKICAgICAgICB5bGFiPSJwcG0iKQpgYGAKClRocm91Z2ggdGhlIHF1aWNrIGFuYWx5c2lzIG9mIHRoZSBmaXJzdCBoZWF0bWFwLCBpdCBjYW4gYmUgc3VnZ2VzdGVkIHRoYXQgc2V2ZXJhbCBwcG1zIGhhZCBsb3dlciBpbnRlbnNpdGllcyBpbiBzYW1wbGVzIG9mIEFIIGluIGNvbXBhcmlzb24gd2l0aCB0aGUgb25lcyBvZiB0aGUgY29ybmVhLiBJbiB0aGUgc2Vjb25kIGhlYXRtYXAsIGl0IGNhbiBiZSBzZWVuIGEgY2xlYXIgZGlmZmVyZW5jZSBpbiBpbnRlbnNpdGllcyBiZXR3ZWVuIHRoZSBzYW1wbGVzIG9mIHBhdGllbnRzIHdpdGggS0MgYW5kIG90aGVycywgc2luY2UgdGhlcmUgaXMgbG93ZXIgaW50ZW5zaXRpZXMgYXNzb2NpYXRlZCB3aXRoIEtDIHNhbXBsZXMuIEZpbmFsbHksIGxvb2tpbmcgYXQgdGhlIGxhc3QgaGVhdG1hcCwgaXQgY2FuIGJlIHZlcmlmaWVkIHRoYXQgZm9yIHRoZSBzYW1wbGVzIG9mIEFIIGZyb20gS0MgcGF0aWVudHMgKEtlcmF0QUgpICwgdGhlIGRldGVjdGlvbiByZXZlYWxlZCBsb3dlciBpbnRlbnNpdGllcyBpbiBjb21wYXJpc29uIHRvIHRoZSBzYW1wbGVzIG9mIHRoZSBjb250cm9sJ3MgQUggKE5vcm1BSCksIHdoZXJlYXMgZm9yIDUuMTcsIDYuMDQsIDYuNDcgYW5kIDMuNTQgcHBtIHRoZSByZXN1bHQgd2FzIHRoZSBjb250cmFyeS4gRm9yIHRoZSBvdGhlciBzYW1wbGVzLCB0aGUgaW50ZW5zaXR5IHZhbHVlcyB3ZXJlIGFwcGFyYW50bHkgc2ltaWxhci4KCgojIE1ldGFib2xpdGUgSWRlbnRpZmljYXRpb24KClRoZSBpZGVudGlmaWNhdGlvbiBvZiB0aGUgbWV0YWJvbGl0ZXMgaW4gdGhlIGRhdGFzZXQgd2FzIG9idGFpbmVkIHVzaW5nIFNwZWNtaW5lLCB3aXRoIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyIE1ldGFib2xpdGUgSWRlbnRpZmljYXRpb24sIGV2YWw9Rn0KbWV0YWJvbGl0ZXNfSUQgPSBubXJfaWRlbnRpZmljYXRpb24oZGF0YXNldCA9IE1UQkxTNDQ0X1NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IDI1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWNsID0gIjFIIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3QubWF4UGVha3MgPSA0MCwgCmNsdXN0Lm5Ub3A9NSkKYGBgCgpUaGUgZXhwZXJpbWVudGFsIGRhdGEgd2FzIG9idGFpbmVkIHVzaW5nIDFILU5NUiA3MDAgTUh6IGF0IDI1wrpDLCBhbmQgU3BlY21pbmUgZG9lcyBub3QgaGF2ZSBzcGVjaWZpYyBsaWJyYXJpZXMgZm9yIGlkZW50aWZpY2F0aW9uIG9mIDcwMCBNSHogTk1SLiBUaGlzIGNhbiBsZWFkIHRvIHByb2JsZW1zIGluIHRoZSBpZGVudGlmaWNhdGlvbiBvZiBtZXRhYm9saXRlcyBwcmVzZW50IGluIHRoZSBkYXRhc2V0LgoKYGBge3IgSE1EQiAtIFBQTVMgY3Jvc3MgcmVmZXJlbmNlfQppZF9tZXRhYnM9YygpCnBwbXM9YygpCmZvciAoY2x1c3RlciBpbiBtZXRhYm9saXRlc19JRCl7CiAgaWRfbWV0YWJzPWMoaWRfbWV0YWJzLCBuYW1lcyhjbHVzdGVyJHN1bW1hcnkpKQp9Cgpmb3IgKGNsdXN0ZXIgaW4gbWV0YWJvbGl0ZXNfSUQpewogIGZvciAobWV0YWJvbGl0ZXMubWF0Y2hlZCBpbiBjbHVzdGVyJG1ldGFib2xpdGVzLm1hdGNoZWQpewogICAgcHBtcz1jKHBwbXMsIG1ldGFib2xpdGVzLm1hdGNoZWQkbWF0Y2hlZF9wZWFrc19yZWYpCiAgfQp9CgptZXRhYm9saXRlcz1kYXRhLmZyYW1lKGlkX21ldGFicywgcHBtcykKYXMuZGF0YS5mcmFtZShtZXRhYm9saXRlcykKYGBgCgpBIHN1bW1hcnkgdGFibGUgb2YgdGhlIGlkZW50aWZpZWQgSE1EQiBJRHMgYW5kIGNvcnJlc3BvbmRpbmcgcHBtcyBjYW4gYmUgc2VlbiBpbiB0aGUgdGFibGUgYWJvdmUuCgpgYGB7ciBTaWduaWZpY2FudCBITURCLCBldmFsPUZ9Cm1ldF9maWx0PWMoKQpmb3IgKGkgaW4gMTpucm93KG1ldGFib2xpdGVzKSkKewogIGlmIChhcy5jaGFyYWN0ZXIobWV0YWJvbGl0ZXNbaSwyXSkgJWluJSBjcm9zc190aXNzdWUpewogICAgcHJpbnQobWV0YWJvbGl0ZXNbaSwxXSkKICAgIG1ldF9maWx0PWMobWV0X2ZpbHQsYXMuY2hhcmFjdGVyKG1ldGFib2xpdGVzW2ksMV0pKQogIH0KfQptZXRfZmlsdF90aXNzdWUgPSBtZXRfZmlsdAoKbWV0X2ZpbHQ9YygpCmZvciAoaSBpbiAxOm5yb3cobWV0YWJvbGl0ZXMpKQp7CiAgaWYgKGFzLmNoYXJhY3RlcihtZXRhYm9saXRlc1tpLDJdKSAlaW4lIGNyb3NzX2Rpc2Vhc2UpewogICAgcHJpbnQobWV0YWJvbGl0ZXNbaSwxXSkKICAgIG1ldF9maWx0PWMobWV0X2ZpbHQsYXMuY2hhcmFjdGVyKG1ldGFib2xpdGVzW2ksMV0pKQogIH0KfQptZXRfZmlsdF9kaXNlYXNlID0gbWV0X2ZpbHQKCm1ldF9maWx0PWMoKQpmb3IgKGkgaW4gMTpucm93KG1ldGFib2xpdGVzKSkKewogIGlmIChhcy5jaGFyYWN0ZXIobWV0YWJvbGl0ZXNbaSwyXSkgJWluJSBhbm92YV9pbnRlcmFjdGlvbl9tZXRhYm9saXRlcyl7CiAgICBwcmludChtZXRhYm9saXRlc1tpLDFdKQogICAgbWV0X2ZpbHQ9YyhtZXRfZmlsdCxhcy5jaGFyYWN0ZXIobWV0YWJvbGl0ZXNbaSwxXSkpCiAgfQp9Cm1ldF9maWx0X2ludGVyYWN0aW9uID0gbWV0X2ZpbHQKYGBgCgpGaWx0ZXJpbmcgb2YgdGhlIGlkZW50aWZpZWQgbWV0YWJvbGl0ZXMgd2FzIHBlcmZvcm1lZCwgd2hlcmUgb25seSB0aGUgcHBtcyBpZGVudGlmaWVkIHdpdGggZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gd2VyZSBrZXB0LgoKYGBge3IgY29udmVydCBITURCIHRvIEtFR0csIGV2YWw9Rn0KaWRfZmlsdF90aXNzdWUgPSBjb252ZXJ0X2htZGJfdG9fa2VnZyhtZXRfZmlsdF90aXNzdWUpCmlkX2ZpbHRfZGlzZWFzZSA9IGNvbnZlcnRfaG1kYl90b19rZWdnKG1ldF9maWx0X2Rpc2Vhc2UpCmlkX2ZpbHRfaW50ZXJhY3Rpb24gPSBjb252ZXJ0X2htZGJfdG9fa2VnZyhtZXRfZmlsdF9pbnRlcmFjdGlvbikKYGBgCgpUaGUgSE1EQiBJRHMgb2YgdGhlIGlkZW50aWZpZWQgbWV0YWJvbGl0ZXMgd2VyZSBjb252ZXJ0ZWQgdG8gY29tcG91bmQgS0VHRyBJRHMgd2l0aCB0aGUgZm9sbG93aW5nIGNvZGUuCgpgYGB7ciBmaW5hbCBtZXRhYm9saXRlc30KYXMuZGF0YS5mcmFtZShpZF9maWx0X3Rpc3N1ZSkgCmFzLmRhdGEuZnJhbWUoaWRfZmlsdF9kaXNlYXNlKQphcy5kYXRhLmZyYW1lKGlkX2ZpbHRfaW50ZXJhY3Rpb24pCmBgYAoKQWZ0ZXIgZmlsdGVyaW5nIHRoZSBpZGVudGlmaWVkIElEcywgb25seSAyIG1ldGFib2xpdGVzIHJlbWFpbjogR2x5Y2luZSwgYW5kIERpaHlkcm91cmFjaWwuCkdseWNpbmUgaXMgYSBwcm90ZWlub2dlbmljIGFtaW5vIGFjaWQgYW5kIERpaHlkcm91cmFjaWwgaXMgYW4gaW50ZXJtZWRpYXRlIGluIGNhdGFib2xpc20gb2YgVXJhY2lsLgoKCiMgUGF0aHdheSBBbmFseXNpcwoKVG8gYW5hbHlzZSB0aGUgcGF0aHdheXMgb2YgdGhlIGNvbXBvdW5kcyBpbnZvbHZlZCBpbiB0aGUgZGF0YXNldCwgd2UgZmlyc3Qgb2J0YWluZWQgdGhlIG9yZ2FuaXNtIGNvZGUgZm9yIEhvbW8gc2FwaWVucyB1c2VkIGluIEtFR0cuCgpgYGB7ciBPcmdhbmlzbSBJRCwgZXZhbD1GfQpnZXRfT3JnYW5pc21zQ29kZXMoKSAjaHVtYW4gY29kZSAtPiBoc2EKYGBgCgpLRUdHIHBhdGh3YXlzIElEJ3MgYXJlIGNvbXBvc2VkIG9mIDIgZWxlbWVudHMuIFRoZSBmaXJzdCBpcyBhIHByZWZpeCwgY29tcG9zZWQgZW50aXJlbHkgb2YgbGV0dGVycyByZXByZXNlbnRpbmcgdGhlIG9yZ2FuaXNtIGFuZCBhIHN1ZmZpeCByZXByZXNlbnRpbmcgdGhlIHBhdGh3YXkuCgpgYGB7ciBQYXRod2F5cywgZXZhbD1GfQp0aXNzdWVfcGF0aHMgPSBnZXRfcGF0aHNfd2l0aF9jcGRzX29yZygiaHNhIiwgaWRfZmlsdF90aXNzdWUpCmRpc2Vhc2VfcGF0aHMgPSBnZXRfcGF0aHNfd2l0aF9jcGRzX29yZygiaHNhIiwgaWRfZmlsdF9kaXNlYXNlKQppbnRlcmFjdGlvbl9wYXRocyA9IGdldF9wYXRoc193aXRoX2NwZHNfb3JnKCJoc2EiLCBpZF9maWx0X2ludGVyYWN0aW9uKQpgYGAKYGBge3IgUGF0aHdheXMgcHJpbnQsIGV2YWw9Rn0KdGlzc3VlX3BhdGhzIApkaXNlYXNlX3BhdGhzCmludGVyYWN0aW9uX3BhdGhzIApgYGAKCldlIHByb2NlZWRlZCB3aXRoIHRoZSBpZGVudGlmaWNhdGlvbiBvZiB0aGUgcGF0aHdheXMgZnJvbSBodW1hbiBtZXRhYm9saXNtIHRoYXQgY29udGFpbiBhdCBsZWFzdCBvbmUgb2YgdGhlIG1ldGFib2xpdGVzIGlkZW50aWZpZWQgYXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGZvciBhbGwgY29uZGl0aW9ucy4KClNpbmNlIHRoZSBvbmx5IG1ldGFib2xpdGVzIGlkZW50aWZpZWQgYXJlIERpaHlkcm91cmFjaWwgYW5kIEdseWNpbmUsIHNvbWUgb2YgdGhlIGlkZW50aWZpZWQgcGF0aHdheXMgb3ZlcmxhcC4KCiMjIFB5cmltaWRpbmUgbWV0YWJvbGlzbSAtIGhzYTAwMjQwCmBgYHtyIGV2YWwgPSBGfQpoc2EwMDI0MF90ID0gcGF0aHdheV9hbmFseXNpcyhpZF9maWx0X3Rpc3N1ZSwKICAgICAgICAgICAgICAgICAiaHNhMDAyNDAiLAogICAgICAgICAgICAgICAgIG5vZGVOYW1lcz0ibmFtZXMiLAogICAgICAgICAgICAgICAgIG1hcC56b29tPUYsCiAgICAgICAgICAgICAgICAgbm9kZVRvb2x0aXA9VCkKCmhzYTAwMjQwX2QgPSBwYXRod2F5X2FuYWx5c2lzKGlkX2ZpbHRfZGlzZWFzZSwKICAgICAgICAgICAgICAgICAiaHNhMDAyNDAiLAogICAgICAgICAgICAgICAgIG5vZGVOYW1lcz0ibmFtZXMiLAogICAgICAgICAgICAgICAgIG1hcC56b29tPUYsCiAgICAgICAgICAgICAgICAgbm9kZVRvb2x0aXA9VCkKYGBgCgpgYGB7cn0KaHNhMDAyNDBfdApoc2EwMDI0MF9kCmBgYAoKIyMgR2x5Y2luZSwgc2VyaW5lIGFuZCB0aHJlb25pbmUgbWV0YWJvbGlzbQpgYGB7ciBldmFsID0gRn0KaHNhMDAyNjBfdCA9IHBhdGh3YXlfYW5hbHlzaXMoaWRfZmlsdF90aXNzdWUsCiAgICAgICAgICAgICAgICAgImhzYTAwMjYwIiwKICAgICAgICAgICAgICAgICBub2RlTmFtZXM9Im5hbWVzIiwKICAgICAgICAgICAgICAgICBtYXAuem9vbT1GLAogICAgICAgICAgICAgICAgIG5vZGVUb29sdGlwPVQpCmBgYAoKYGBge3J9CmhzYTAwMjYwX3QKYGBgCgojIyBHbHV0YXRoaW9uZSBtZXRhYm9saXNtIC0gaHNhMDA0ODAKYGBge3IgZXZhbCA9IEZ9CmhzYTAwNDgwX3QgPSBwYXRod2F5X2FuYWx5c2lzKGlkX2ZpbHRfdGlzc3VlLAogICAgICAgICAgICAgICAgICJoc2EwMDQ4MCIsCiAgICAgICAgICAgICAgICAgbm9kZU5hbWVzPSJuYW1lcyIsCiAgICAgICAgICAgICAgICAgbWFwLnpvb209RiwKICAgICAgICAgICAgICAgICBub2RlVG9vbHRpcD1UKQpgYGAKCmBgYHtyfQpoc2EwMDQ4MF90CmBgYAoKQ29uc2lkZXJpbmcgdGhlIE5NUiBhbmFseXNpcyBkb25lIGJ5IFNueXRrb3ZhIGFuZCBjb29wZXJhdG9ycyAoMjAxNykgYW5kIHRoZSBwcmV2aW91cyBmaWx0ZXJpbmcgb2YgZGF0YSwgR2x5Y2luZSBpcyB0aGUgb25seSBsaWFibGUgbWV0YWJvbGl0ZSBmb3IgZnVydGhlciBldmFsdWF0aW9uIG9mIHBhdGh3YXlzLgpHbHljaW5lIGlzIGEgbWFqb3IgY29tcG91bmQgaW4gdmVydGVicmF0ZXMgYXMgaXQncyBhbiBpbXBvcnRhbnQgY29tcG9uZW50IGluIG51bWVyb3VzIHByb2Nlc3NlcyBpbiB0aGUgY2VudHJhbCBuZXJ2b3VzIHN5c3RlbSwgYW5kIG1vc3QgaW1wb3J0YW50bHksIGluIHN5bmFwdGljIHRyYW5zcG9ydGF0aW9uLiBBcyBzdWNoLCBpdCdzIGFuIGltcG9ydGFudCBzdHVkeSB0YXJnZXQgc2luY2UgaXRzIGFiaWxpdHkgdG8gbWVkaWF0ZSBuZXVyb25hbCBzdGltdWxpIGJ5IGFtaW5vYWNpZCB0cmFuc3BvcnQgaW5kaWNhdGVzIGEgcHJvYmFibGUgYWN0aW9uIGluIGNvcnRpY2FsLW9jdWxhciBpbnRlcmFjdGlvbi4KQWZ0ZXIgYSB0aG9yb3VnaCBsaXRlcmF0dXJlIHNlYXJjaCBvbiBHbHV0YXRoaW9uZSAoR1NIKSBhbmQgUHlyaW1pZGluZSBwYXRod2F5cywgaXQgd2FzIGZvdW5kIHRoYXQgR1NIIGhhcyBhIHNpZ25pZmljYW50IHZhcmlhdGlvbiBpbiBpdCdzIGNvbmNlbnRyYXRpb24gb24gYnJhaW4gdGlzc3VlcyBpbiBhIGRldGVybWluZWQgcG9zdCBtb3J0ZW0gaW50ZXJ2YWwgKFBNSSksIGluZGljYXRpbmcgYSBtYWpvciBtZXRhYm9saWMgc2hpZnQgaW4gdGhpcyBwYXRod2F5LiBUaGUgaWRlbnRpZmllZCBicmFpbiBjZWxscyB3aXRoIG1ham9yIHZhcmlhdGlvbnMgaW4gR1NIIHdlcmUgb2YgdGhlIENlcmVicmFsIENvcnRleCBhbmQgY2VyZWJlbGx1bSwgdHdvIG1haW4gY3VscHJpdHMgZm9yIGV5ZSBmdW5jaW9uIGluIGh1bWFucyAoSGFyaXNoIGV0IGFsLiwgMjAxMSkuIEFzIGZvciBweXJpbWlkaW5lIHN5bnRoZXNpcy4gQSAyMDE1IHN0dWR5IGJ5IENvc3RhIGFuZCBoZXIgY29sbGVhZ3VlcyBmb3VuZCB0aGF0IGluIGEgUE1JIG9mIDIsNiB0byAyNGgsIGEgc2lnbmlmaWNhbnQgaW5jcmVhc2UgaW4gdXJlYSBwcm9kdWN0aW9uIHdhcyByZXBvcnRlZCBpbiBodW1hbiB0aXNzdWVzLCBtYWlubHkgaW4gYmxvb2QsIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiB0aGUgb2N1bGFyIHRpc3N1ZSBWaXRyZW91cyBIdW1vciwgd2hpY2ggaW4gdHVybiByZW1haW5zIHJlbGF0aXZlbHkgc3RhYmxlLiBUaGVzZSByZXN1bHRzIGltcGx5IHRoYXQgYSBtYWpvciBjaGFuZ2UgaW4gbWV0YWJvbGl0ZXMgbWF5YmUgYW4gaW5mbHVlbmNlIGluIHRoZXNlIHJlc3VsdHMsIG1haW5seSBhdCB0aGUgbGV2ZWwgb2YgR2x5Y2luZSBtZXRhYm9saXNtLCB0aHJvdWdoIHRoZXNlIHBhdGh3YXlzLgoKCiMgRW5yaWNobWVudCBBbmFseXNpcwoKSW4gb3JkZXIgdG8gb2J0YWluIGEgYmV0dGVyIGdyYXNwIG9mIHRoZSBwb3NzaWJsZSBlbnp5bWVzIGFuZCByZWFjdGlvbnMgYWx0ZXJlZCBpbiB0aGUgZGlmZmVyZW50IGNvbmRpdGlvbnMsIHdlIHBlcmZvcm1lZCBhIG1ldGFib2xpdGUgZW5yaWNobWVudCBhbmFseXNpcyB1c2luZyBGRUxMQS4KCmBgYHtyIEZlbGxhIGRhdGFiYXNlLCBldmFsPUZ9CnNldC5zZWVkKDEpCiMgRmlsdGVyIG92ZXJ2aWV3IHBhdGh3YXlzCmdyYXBoIDwtIGJ1aWxkR3JhcGhGcm9tS0VHR1JFU1QoCiAgb3JnYW5pc20gPSAiaHNhIiwKICBmaWx0ZXIucGF0aCA9IGMoIjAwOTcwIiwgIjAwMTIwIiwgIjAwMjQwIiwgIjAwMjYwIiwgIjAwNjMwIiwiMDA4NjAiLCIwMDQ4MCIsIjAwNDEwIiwiMDA3NzAiKSkKCnRtcGRpciA8LSBwYXN0ZTAodGVtcGRpcigpLCAiL215X2RhdGFiYXNlIikKIyBNa2Ugc3VyZSB0aGUgZGF0YWJhc2UgZG9lcyBub3QgZXhpc3QgZnJvbSBhIGZvcm1lciB2aWduZXR0ZSBidWlsZAojIE90aGVyd2lzZSB0aGUgdmlnbmV0dGUgd2lsbCByaXNlIGFuIGVycm9yCiMgYmVjYXVzZSBGRUxMQSB3aWxsIG5vdCBvdmVyd3JpdGUgYW4gZXhpc3RpbmcgZGF0YWJhc2UKdW5saW5rKHRtcGRpciwgcmVjdXJzaXZlID0gVFJVRSkKYnVpbGREYXRhRnJvbUdyYXBoKAogIGtlZ2dkYXRhLmdyYXBoID0gZ3JhcGgsCiAgZGF0YWJhc2VEaXIgPSB0bXBkaXIsCiAgaW50ZXJuYWxEaXIgPSBGQUxTRSwKICBtYXRyaWNlcyA9ICJkaWZmdXNpb24iLAogIG5vcm1hbGl0eSA9ICJkaWZmdXNpb24iLAogIG5pdGVyID0gNTApCgpmZWxsYS5kYXRhIDwtIGxvYWRLRUdHZGF0YSgKICBkYXRhYmFzZURpciA9IHRtcGRpciwKICBpbnRlcm5hbERpciA9IEZBTFNFLAogIGxvYWRNYXRyaXggPSAiZGlmZnVzaW9uIgopCmBgYApgYGB7cn0KZmVsbGEuZGF0YQpgYGAKCkZpcnN0LCB0aGUgRkVMTEEgZGF0YWJhc2Ugd2FzIGNyZWF0ZWQsIHVzaW5nIG9ubHkgcGF0aHdheXMgaWRlbnRpZmllZCBwcmV2aW91c2x5IGFuZCBkYXRhIGZyb20gS0VHRwoKYGBge3IgY29tcG91bmQgSURTLCBldmFsPUZ9CnRpc3N1ZV9jb21wID0gdW5pcXVlKHN1YnN0cmluZyh0ZXh0ID0gdGlzc3VlX3BhdGhzJGNvbXBvdW5kcywgNSkpCmRpc2Vhc2VfY29tcCA9IHVuaXF1ZShzdWJzdHJpbmcodGV4dCA9IGRpc2Vhc2VfcGF0aHMkY29tcG91bmRzLCA1KSkKaW50ZXJhY3Rpb25fY29tcCA9IHVuaXF1ZShzdWJzdHJpbmcodGV4dCA9IGludGVyYWN0aW9uX3BhdGhzJGNvbXBvdW5kcywgNSkpCmBgYAoKV2UgZXh0cmFjdGVkIHRoZSBjb21wb3VuZCBJRHMgZm9yIGVhY2ggY29uZGl0aW9uLgoKYGBge3IgRW5yaWNobWVudCwgZXZhbD1GfQpjb21wb3VuZHM8LXVuaXF1ZShjKHRpc3N1ZV9jb21wLGRpc2Vhc2VfY29tcCkpCmFuYWx5c2lzPC0gZGVmaW5lQ29tcG91bmRzKAogIGNvbXBvdW5kcyA9IGNvbXBvdW5kcywKICBkYXRhID0gZmVsbGEuZGF0YSkKCmdldEV4Y2x1ZGVkKGFuYWx5c2lzKQoKYW5hbHlzaXMgPC0gcnVuRGlmZnVzaW9uKAogIG9iamVjdCA9IGFuYWx5c2lzLAogIGRhdGEgPSBmZWxsYS5kYXRhLAogIGFwcHJveCA9ICJub3JtYWxpdHkiKQpgYGAKCldlIHByb2NlZWRlZCB3aXRoIHRoZSBlbnJpY2htZW50IGFuYWx5c2lzIHVzaW5nIGRpZmZ1c2luZyBhbGdvcml0aG1zIGFuZCBub3JtYWxpc2F0aW9uIHRocm91Z2ggei1zY29yZS4KCmBgYHtyIGVucmljaG1lbnQgcmVzdWx0c30KdGFiLmFsbCA8LSBnZW5lcmF0ZVJlc3VsdHNUYWJsZSgKICBtZXRob2QgPSAiZGlmZnVzaW9uIiwKICBubGltaXQgPSAxNSwKICBvYmplY3QgPSBhbmFseXNpcywKICBkYXRhID0gZmVsbGEuZGF0YSkKCm5saW1pdCA8LSAxNQp2ZXJ0ZXgubGFiZWwuY2V4IDwtIDEKcGxvdCgKICBhbmFseXNpcywKICBtZXRob2QgPSAiZGlmZnVzaW9uIiwKICBkYXRhID0gZmVsbGEuZGF0YSwKICBubGltaXQgPSBubGltaXQsCiAgdmVydGV4LmxhYmVsLmNleCA9IHZlcnRleC5sYWJlbC5jZXgpCgp0YWIuYWxsCmBgYAoKVGhlIHRvcCAxNSBlbnp5bWVzIGFuZCByZWFjdGlvbnMgZW5yaWNoZWQgaW4gdGhlc2Ugc2V0cywgb3JkZXJlZCBieSBwLnNjb3JlLCBjYW4gYmUgc2VlbiBpbiB0aGUgdGFibGUuIFRoZWlyIHJlbGF0aW9uc2hpcCB0byBlYWNoIG90aGVyIGFuZCB0byBHbHljaW5lIGFuZCBEaWh5ZHJvdXJhY2lsIGNhbiBiZSBzZWVuIGluIHRoZSBub2RlIGdyYXBoLgoKIyBQQ0EKCkluIG9yZGVyIHRvIGV4cGxvcmUgdGhlIHJlbGF0ZWRuZXNzIG9mIG91ciBzYW1wbGVzIHdlIHBlcmZvcm1lZCBhIFBDQSBhbmFseXNpcy4KCmBgYHtyIFBDQX0KTVRCTFM0NDRfcGNhPXBjYV9hbmFseXNpc19kYXRhc2V0KE1UQkxTNDQ0X1NjYWxlZCxzY2FsZT1GKQpNVEJMUzQ0NF9pbXBvcnRhbmNlPXBjYV9pbXBvcnRhbmNlKE1UQkxTNDQ0X3BjYSkKCmFzLmRhdGEuZnJhbWUoTVRCTFM0NDRfaW1wb3J0YW5jZVsxLF0pCnBsb3QoTVRCTFM0NDRfaW1wb3J0YW5jZVsxLF0seWxhYiA9ICJTdGFuZGFyZCBkZXZpYXRpb24iLAogICAgICB4bGFiID0gIlByaW5jaXBhbCBDb21wb25lbnQiLAogICAgICBtYWluPSJTdGFuZGFyZCBkZXZpYXRpb24gdnMgUHJpbmNpcGFsIENvbXBvbmVudCIsIHBjaD0xOSwKICAgICAgY29sPSJibHVlIiwKICAgICAgdHlwZT0icCIsIHhheHQ9Im4iKQpheGlzKDEsIGF0ID0gc2VxKDEsIDQ0LCBieSA9IDEpLCBsYXM9MikKYWJsaW5lKGg9MSkKYGBgCgpJbiB0aGVzZSByZXN1bHRzLCB0aGUgZmlyc3QgMjAgcHJpbmNpcGFsIGNvbXBvbmVudHMgaGF2ZSBzdGFuZGFyZCBkZXZpYXRpb24gZ3JlYXRlciB0aGFuIDEgKEthaXNlciBjcml0ZXJpb24pLgpUaGVzZSB0aHJlZSBjb21wb25lbnRzIGV4cGxhaW4gOTAsMTElIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIGRhdGEuClRoZSBwbG90IHNob3dzIHRoYXQgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBzdGFydHMgdG8gZm9ybSBhIGxpbmUgd2l0aCBoaWdoZXIgc2xvcGUgdW50aWwgdGhlIHNpeHRoIGNvbXBvbmVudC4gVGhpcyBtZWFucyB0aGF0IHRoZSBmaXJzdCBzaXggUENzIGhhdmUgbW9yZSBpbmZsdWVuY2UgaW4gdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSBkYXRhLiAKTmV2ZXJ0aGVsZXNzLCB0aGUgZmlyc3QgMiBQQ3MgYXJlLCB3aXRob3V0IGEgZG91YnQsIHRoZSBtYWluIGluZmx1ZW5jZXMgaW4gdGhlIGRhdGEgdmFyaWFiaWxpdHksIHNpbmNlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gYmV0d2VlbiB0aGVtIGFuZCB0aGUgZm9sbG93aW5nIG9uZXMgaXMgYWxtb3N0IDEgdW5pdC4KCmBgYHtyfQphcy5kYXRhLmZyYW1lKE1UQkxTNDQ0X2ltcG9ydGFuY2VbMixdKQpwbG90KE1UQkxTNDQ0X2ltcG9ydGFuY2VbMixdLHlsYWIgPSAiUHJvcG90aW9uIG9mIFZhcmlhbmNlIiwKICAgICB4bGFiID0gIlByaW5jaXBhbCBDb21wb25lbnQiLAogICAgIG1haW49IlByb3BvdGlvbiBvZiBWYXJpYW5jZSB2cyBQcmluY2lwYWwgQ29tcG9uZW50IiwgcGNoPTE5LAogICAgIGNvbD0icmVkIiwKICAgICB0eXBlPSJwIiwgeGF4dD0ibiIpCmF4aXMoMSwgYXQgPSBzZXEoMSwgNDQsIGJ5ID0gMSksIGxhcz0yKQpgYGAKCldlIGNhbiB1c2UgdGhlIHByb3BvcnRpb24gdG8gZGV0ZXJtaW5lIHdoaWNoIHByaW5jaXBhbCBjb21wb25lbnRzIGV4cGxhaW4gbW9zdCBvZiB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRhdGEuClRoZSBoaWdoZXIgdGhlIHByb3BvcnRpb24sIHRoZSBtb3JlIHZhcmlhYmlsaXR5IHRoYXQgdGhlIHByaW5jaXBhbCBjb21wb25lbnQgZXhwbGFpbnMuClRoZSBzaXplIG9mIHRoZSBwcm9wb3J0aW9uIGNhbiBoZWxwIHRvIGRlY2lkZSB3aGV0aGVyIHRoZSBwcmluY2lwYWwgY29tcG9uZW50IGlzIGltcG9ydGFudCBlbm91Z2ggdG8gcmV0YWluLgpJbiB0aGUgcGxvdCBpdCBpcyBldmlkZW50IHRoYXQgdGhlIHByb3BvcnRpb24gdmFsdWUgZGVjbGluZXMgcmFwaWRseSB3aXRoaW4gdGhlIGZpcnN0IHRocmVlIFBDcy4KU28sIGl0IGNhbiBiZSBzdGF0ZWQgdGhhdCB0aGV5IGFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgb25lcy4KCmBgYHtyfQphcy5kYXRhLmZyYW1lKE1UQkxTNDQ0X2ltcG9ydGFuY2VbMyxdKQpwbG90KE1UQkxTNDQ0X2ltcG9ydGFuY2VbMyxdLHlsYWIgPSAiQ3VtdWxhdGl2ZSBQcm9wb3J0aW9uIiwKICAgICB4bGFiID0gIlByaW5jaXBhbCBDb21wb25lbnQiLAogICAgIG1haW49IkN1bXVsYXRpdmUgUHJvcG9ydGlvbiB2cyBQcmluY2lwYWwgQ29tcG9uZW50IiwgcGNoPTE5LAogICAgIGNvbD0iZ3JlZW4iLAogICAgIHR5cGU9InAiLCB4YXh0PSJuIikKYXhpcygxLCBhdCA9IHNlcSgxLCA0NCwgYnkgPSAxKSwgbGFzPTIpCmFibGluZShoPS45KQphYmxpbmUodj0yMCwgbHR5PTIpCmFibGluZShoPS42NikKYWJsaW5lKHY9NywgbHR5PTIpCmBgYAoKVGhlIGN1bXVsYXRpdmUgcHJvcG9ydGlvbiBpcyB1c2VkIHRvIGFzc2VzcyB0aGUgdG90YWwgYW1vdW50IG9mIHZhcmlhbmNlIHRoYXQgdGhlIGNvbnNlY3V0aXZlIHByaW5jaXBhbCBjb21wb25lbnRzIGV4cGxhaW4uCkhlbmNlLCBhcyB3ZSBjYW4gc2VlLCB0aGUgZmlyc3QgMjAgUENzIGV4cGxhaW4gOTAgJSBvZiB0aGUgZGF0YSB2YXJpYWJpbGl0eSwgd2hlcmVhcyBhbG1vc3QgMi8zIG9mIHRoZSBkYXRhIHZhcmlhYmlsaXR5IGlzIGV4cGxhaW5lZCBieSB0aGUgZmlyc3QgNyBQQ3MuCgoKYGBge3J9CnZhcmlhYmlsaWRhZGVfOTA9bWluKHdoaWNoKE1UQkxTNDQ0X2ltcG9ydGFuY2VbMyxdPjAuOSkpCnZhcmlhYmlsaWRhZGVfOTAKYGBgCgoyMCBjb21wb25lbnRzIHRoYXQgZXhwbGFpbiA5MCUgb2YgdmFyaWFiaWxpdHkKCmBgYHtyfQpwYXIobWZyb3c9YygxLDIpKQpwbG90KE1UQkxTNDQ0X3BjYSR4WywxXSxNVEJMUzQ0NF9wY2EkeFssMl0sIGNvbD1hcy5pbnRlZ2VyKE1UQkxTNDQ0JG1ldGFkYXRhJFRpc3N1ZSksCiAgICAgeWxhYiA9ICJQQzIiLAogICAgIHhsYWIgPSAiUEMxIiwKICAgICBtYWluPSJTY29yZXMiLCBwY2g9MTksCiAgICAgdHlwZT0icCIsCiAgICAgeWxpbT1jKC04LDE1KSwKICAgICB4bGltPWMoLTgsMTUpKQphYmxpbmUoaD0wLCBsdHk9MikKYWJsaW5lKHY9MCwgbHR5PTIpCmxlZ2VuZCgidG9wcmlnaHQiLGxlZ2VuZD1jKCJBcXVlb3VzIEh1bW9yIiwiY29ybmVhIiksIGNvbD1jKCJibGFjayIsInJlZCIpICwgcGNoPTE5LCBjZXg9MC43NSkKCgoKcGxvdChNVEJMUzQ0NF9wY2EkeFssMV0sTVRCTFM0NDRfcGNhJHhbLDJdLCBjb2w9YXMuaW50ZWdlcihNVEJMUzQ0NCRtZXRhZGF0YSREaXNlYXNlKSwKICAgICB5bGFiID0gIlBDMiIsCiAgICAgeGxhYiA9ICJQQzEiLAogICAgIG1haW49IlNjb3JlcyIsIHBjaD0xOSwKICAgICB0eXBlPSJwIiwKICAgICB5bGltPWMoLTgsMTUpLAogICAgIHhsaW09YygtOCwxNSkpCmFibGluZShoPTAsIGx0eT0yKQphYmxpbmUodj0wLCBsdHk9MikKbGVnZW5kKCJ0b3ByaWdodCIsbGVnZW5kPWMoIktlcmF0b2NvbnVzIiwibm9uZSIpLCBjb2w9YygiYmxhY2siLCJyZWQiKSAsIHBjaD0xOSwgY2V4PS43NSkKCgoKcGxvdChNVEJMUzQ0NF9wY2EkeFssMV0sTVRCTFM0NDRfcGNhJHhbLDJdLCBjb2w9YyhyZXAoMSw3KSxyZXAoMiwxMSkscmVwKDMsMTMpLHJlcCg0LDEzKSksCiAgICAgeWxhYiA9ICJQQzIiLAogICAgIHhsYWIgPSAiUEMxIiwKICAgICBtYWluPSJTY29yZXMiLCBwY2g9MTksCiAgICAgdHlwZT0icCIsCiAgICAgeWxpbT1jKC04LDE1KSwKICAgICB4bGltPWMoLTgsMTUpKQphYmxpbmUoaD0wLCBsdHk9MikKYWJsaW5lKHY9MCwgbHR5PTIpCmxlZ2VuZCgidG9wcmlnaHQiLGxlZ2VuZD1jKCJLZXJhdEFIIiwiS2VyYXRDb3JuIiwgIk5vcm1BSCIsICJOb3JtQ29ybiIpLCBjb2w9YygiYmxhY2siLCJyZWQiLCJncmVlbiIsImJsdWUiKSAsIHBjaD0xOSkKYGBgCgpBcyBjYW4gYmUgc2VlbiBpbiB0aGUgcGxvdCBvZiB0aGUgc2NvcmVzLCB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gdGhlIGluZmx1ZW5jZSBvZiB0aGUgZGF0YSByZWxhdGVkIHRvIHRoZSBkaWZmZXJlbnQgc2FtcGxlcyBhbmQgdGhlIHR3byBmaXJzdCBjb21wb25lbnRzLgpJbiBnZW5lcmFsLCB0aGUgc2FtcGxlcyBvZiBOb3JtQUggd2VyZSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgd2l0aCBQQzEuCldoZXJlYXMgdGhlIHNhbXBsZXMgb2YgQ29ybmVhIHdlcmUgbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggYm90aCBQQzEgYW5kIFBDMi4KCkZpbmFsbHksIHRoZSBzYW1wbGVzIG9mIEtlcmF0QUggKGFxdWVvdXMgaHVtb3Igb2YgcGF0aWVudHMgd2l0aCBLZXJhdG9jb251cykgd2VyZSBhbGwgcG9zaXRpdmVseSBjb3JyZWxhdGVkIHRvIFBDMiwgYWNoaWV2aW5nIHNjb3JlIHZhbHVlcyBvZiAxMi42NiBhbmQgMTAuNy4KCkV2ZW4gdGhvdWdoIGNvcm5lYSBzYW1wbGVzIHJldmVhbGVkIHRvIGJlIHZlcnkgc2ltaWxhciBjb25jZXJuaW5nIHRoZSBjb3JyZWxhdGlvbiB3aXRoIGJvdGggUENzLApUaGUgc2NvcmVzIHJlbGF0ZWQgdG8gc2FtcGxlcyBvZiBBcXVlb3VzIEh1bW9yIHN1Z2dlc3QgYSBkaWZmZXJlbmNlIHdpdGhpbiBzYW1wbGVzIGV4dHJhY3RlZCBmcm9tIGh1bWFucyBpbiBkaWZmZXJlbnQgY29uZGl0aW9ucyAod2l0aCBhbmQgd2l0aG91dCBkaXNlYXNlKSwgc2ltaWxhcmx5IHRvIHdoYXQgd2FzIHN1Z2dlc3RlZCBieSB0aGUgaGVhdG1hcHMgZ2VuZXJhdGVkIHByZXZpb3VzbHkuCgpgYGB7cn0KcGxvdChNVEJMUzQ0NF9wY2Ekcm90YXRpb25bLDE6Ml0sICAgIyB4IGFuZCB5IGRhdGEKICAgICBwY2g9MjEsICAgICAgICAgICAgICAjIHBvaW50IHNoYXBlCiAgICAgYmc9ImJsYWNrIiwgICAgICAgICAgIyBwb2ludCBjb2xvcgogICAgIGNleD0xLCAgICAgICAgICAgICAgICMgcG9pbnQgc2l6ZQogICAgIG1haW49IkxvYWRpbmdzIG9mIGFsbCBjaGVtaWNhbCBzaGlmdHMiICAgICAgIyB0aXRsZSBvZiBwbG90CikKdGV4dChNVEJMUzQ0NF9wY2Ekcm90YXRpb25bLDE6Ml0sICAgICAgICAgICAgICMgc2V0cyBwb3NpdGlvbiBvZiBsYWJlbHMKICAgICBsYWJlbHM9cm93bmFtZXMoTVRCTFM0NDRfcGNhJHJvdGF0aW9uKSAjIHByaW50IGxhYmVscwopCgoKcGFyKG1mcm93PWMoMSwyKSkKYmFycGxvdChNVEJMUzQ0NF9wY2Ekcm90YXRpb25bYygiMy40MyIsIjMuNTQiKSwxXSwgbGFzPTIsIG1haW49ICJMb2FkaW5ncyBmb3IgUEMxIiwgeWxhYj0iTG9hZGluZ3MiLAogICAgICAgIHhsYWI9IkNoZW1pY2FsIFNoaWZ0IiwgeWxpbT1jKC0wLjIsMC4zKSwgY29sPWMoImN5YW4iLCJibHVlIiksIG5hbWVzLmFyZyA9IGMoIkRpaHlkcm91cmFjaWwiLCAiR2x5Y2luZSIpKQpiYXJwbG90KE1UQkxTNDQ0X3BjYSRyb3RhdGlvbltjKCIzLjQzIiwiMy41NCIpLDJdLCBsYXM9MiwgbWFpbj0gIkxvYWRpbmdzIGZvciBQQzIiLCB5bGFiPSJMb2FkaW5ncyIsCiAgICAgICAgeGxhYj0iQ2hlbWljYWwgU2hpZnQiLCB5bGltPWMoLTAuMiwwLjMpLGNvbD1jKCJjeWFuIiwiYmx1ZSIpLCBuYW1lcy5hcmcgPSBjKCJEaWh5ZHJvdXJhY2lsIiwgIkdseWNpbmUiKSkKYGBgCgpgYGB7cn0KcGNhX3BhaXJzX3Bsb3QoTVRCTFM0NDQsIE1UQkxTNDQ0X3BjYSwgIlRpc3N1ZSIsIHBjYXMgPSBjKDEsMiwzKSkKcGNhX3BhaXJzX3Bsb3QoTVRCTFM0NDQsIE1UQkxTNDQ0X3BjYSwgIkRpc2Vhc2UiLCBwY2FzID0gYygxLDIsMykpCgpwY2Ffa21lYW5zX3Bsb3QyRChNVEJMUzQ0NCwgTVRCTFM0NDRfcGNhLCBudW0uY2x1c3RlcnMgPSAyLCBwY2FzID0gYygxLCAyKSkKcGNhX3BhaXJzX2ttZWFuc19wbG90KE1UQkxTNDQ0LCBNVEJMUzQ0NF9wY2EsIG51bS5jbHVzdGVycyA9IDMsIHBjYXM9IGMoMSwyLDMpKQpgYGAKClRoZSBiYXJwbG90cyBhYm92ZSBoYXZlIHRoZSBsb2FkaW5ncyBmb3IgYm90aCBQQzEgYW5kIFBDMiBvZiB0aGUgY2hlbWljYWwgc2hpZnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgbWV0YWJvbGl0ZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLgpBcyBjYW4gYmUgc2VlbiBpbiB0aGUgcGxvdHMsIHRoZSBsb2FkaW5nIHZhbHVlIHJlbGF0ZWQgdG8gMy41NCBzdWdnZXN0IHRoYXQgdGhpcyB2YXJpYWJsZSBzdHJvbmdseSBpbmZsdWVuY2UgUEMxLCB3aGVyZWFzIHRoZSBsb2FkaW5nIHZhbHVlIGZvciAzLjQzIHN1Z2dlc3QgdGhhdCB0aGlzIHZhcmlhYmxlIHN0cm9uZ2x5IGluZmx1ZW5jZXMgUEMyLgoKU2luY2UgUEMyIHdhcyBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgd2l0aCB0aGUgc2FtcGxlcyBvZiBLZXJhdEFILCB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgbWV0YWJvbGl0ZSByZWxhdGVkIHRvIHRoZSBjaGVtaWNhbCBzaGlmdCBvZiAzLjQzIChEaWh5ZHJvdXJhY2lsKSBhbmQgdGhlIGRpc2Vhc2Ugc2VlbXMgcGxhdXNpYmxlLgoKCiMgQ2x1c3RlcmluZwoKQ2x1c3RlcmluZyBhbmFseXNpcyB3YXMgc3Vic2VxdWVudGx5IGRvbmUgdXNpbmcgYm90aCBhIGhpZXJhcmNoaWNhbCBhbmQgYSBLLW1lYW5zIGFsZ29yaXRobSBzaW5jZSBib3RoIGNhbiBoYW5kbGUgdGhlIGFtb3VudCBvZiBkYXRhIG9uIHRoZSBzYW1wbGVzLCBhbmQgcmVzdWx0cyB3ZXJlIGZ1cnRoZXIgYW5hbHlzZWQuCgojIyBIaWVyYXJjaGljYWwgQ2x1c3RlcmluZwoKYGBge3IgSEMgY2x1c3RlcmluZ30KTVRCTFM0NDRfY2x1c3RlcmluZ19oYzwtY2x1c3RlcmluZyhNVEJMUzQ0NF9TY2FsZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJoYyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlID0gInBlYXJzb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0TWV0aG9kID0gInNpbmdsZSIpCmRlbmRyb2dyYW1fcGxvdF9jb2woTVRCTFM0NDRfU2NhbGVkLCAKICAgICAgICAgICAgICAgICAgICBNVEJMUzQ0NF9jbHVzdGVyaW5nX2hjLCAKICAgICAgICAgICAgICAgICAgICAiVGlzc3VlIiwKICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJEZW5kb2dyYW0gYnkgVGlzc3VlIFNhbXBsZXMiLCAKICAgICAgICAgICAgICAgICAgICBsZWcucG9zID0gInRvcHJpZ2h0IikKZGVuZHJvZ3JhbV9wbG90X2NvbChNVEJMUzQ0NF9TY2FsZWQsIAogICAgICAgICAgICAgICAgICAgIE1UQkxTNDQ0X2NsdXN0ZXJpbmdfaGMsIAogICAgICAgICAgICAgICAgICAgICJEaXNlYXNlIiwgCiAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiRGVuZG9ncmFtIGJ5IERpc2Vhc2UvTm9ybWFsIFNhbXBsZXMiLAogICAgICAgICAgICAgICAgICAgIGxlZy5wb3MgPSAidG9wcmlnaHQiKQpgYGAKClRoZW4sIHRoZSByZXNwZWN0aXZlIGRlbmRyb2dyYW0gcGxvdHMgZm9yIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIGRhdGEgd2VyZSBhbmFseXNlZCBib3RoIGFjY29yZGluZyB0byB0aGUgdGlzc3VlLCBhbmQgdG8gdGhlIERpc2Vhc2VkL05vcm1hbCBzdGF0ZXMgb2YgdGhlIGluZGl2aWR1YWxzLiAKCiMjIEstbWVhbnMgQ2x1c3RlcmluZwoKYGBge3IgS21lYW5zIGNsdXN0ZXJpbmd9Ck1UQkxTNDQ0X2NsdXN0ZXJpbmdfa21lYW5zPC1jbHVzdGVyaW5nKE1UQkxTNDQ0X1NjYWxlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJrbWVhbnMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2UgPSAibWFuaGF0dGFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RNZXRob2QgPSAiY2VudHJvaWQiKQoKYXMuZGF0YS5mcmFtZShNVEJMUzQ0NF9jbHVzdGVyaW5nX2ttZWFucyRjbHVzdGVyKQprbWVhbnNfcGxvdChNVEJMUzQ0NF9TY2FsZWQsIE1UQkxTNDQ0X2NsdXN0ZXJpbmdfa21lYW5zKQoKa21lYW5zX3Rpc3N1ZSA9IHRhYmxlKE1UQkxTNDQ0X1NjYWxlZCRtZXRhZGF0YSRUaXNzdWUsIE1UQkxTNDQ0X2NsdXN0ZXJpbmdfa21lYW5zJGNsdXN0ZXIpCgpwYXIobWZyb3c9YygyLDEpKQoKa21lYW5zX3Rpc3N1ZQpiYXJwbG90KGttZWFuc190aXNzdWUsCiAgICAgICAgYmVzaWRlID0gVCwKICAgICAgICBjb2wgPSBjKCJjeWFuIiwiYmx1ZSIpLAogICAgICAgIG1haW4gPSAiS21lYW5zIENsdXN0ZXJpbmcgZnJlcXVlbmN5IGJ5IFRpc3N1ZSIsCiAgICAgICAgeGxhYiA9ICJDbHVzdGVycyIsCiAgICAgICAgeWxhYiA9ICJOdW1iZXIgb2YgU2FtcGxlcyIsCiAgICAgICAgeWxpbSA9IGMoMCwyMCkKICAgICAgICApCmxlZ2VuZCgidG9wcmlnaHQiLAogICAgICAgbGVnZW5kPWMoIktlcmF0b2NvbnVzIiwibm9uZSIpLAogICAgICAgY29sPWMoImN5YW4iLCJibHVlIiksCiAgICAgICBwY2ggPSAxOSwKICAgICAgIHhqdXN0ID0gMC41LCBidHkgPSAibiIpCgprbWVhbnNfZGlzZWFzZSA9IHRhYmxlKE1UQkxTNDQ0X1NjYWxlZCRtZXRhZGF0YSREaXNlYXNlLCBNVEJMUzQ0NF9jbHVzdGVyaW5nX2ttZWFucyRjbHVzdGVyKQoKa21lYW5zX2Rpc2Vhc2UKYmFycGxvdChrbWVhbnNfZGlzZWFzZSwKICAgICAgICBiZXNpZGUgPSBULCAgICAgICAgIAogICAgICAgIGNvbCA9IGMoImN5YW4iLCJibHVlIiksCiAgICAgICAgbWFpbiA9ICJLbWVhbnMgQ2x1c3RlcmluZyBmcmVxdWVuY3kgYnkgQ29uZGl0aW9uIiwKICAgICAgICB4bGFiID0gIkNsdXN0ZXJzIiwKICAgICAgICB5bGFiID0gIk51bWJlciBvZiBTYW1wbGVzIiwKICAgICAgICB5bGltID0gYygwLDIwKQopCgpsZWdlbmQoInRvcHJpZ2h0IiwKICAgICAgIGxlZ2VuZD1jKCJLZXJhdG9jb251cyIsIm5vbmUiKSwKICAgICAgIGNvbD1jKCJjeWFuIiwiYmx1ZSIpLAogICAgICAgcGNoID0gMTksCiAgICAgICB4anVzdCA9IDAuNSwgYnR5ID0gIm4iKQpgYGAKCkZvciB0aGUgayBtZWFucywgZGF0YSB3YXMgYWxzbyBzZXBhcmF0ZWQgYWNjb3JkaW5nIHRvIHRoZSBjb25kaXRpb24sIHBsb3R0ZWQgYW5kIHNob3duIGluIHR3byBhZGRpdGlvbmFsIHRhYmxlcyBmb3IgYmV0dGVyIHVuZGVyc3RhbmRpbmcgb24gaG93IHRoZSBhZ2dyZWdhdGlvbiBvZiBkYXRhIHdhcyBkb25lLgoKSW4gc3VtLCB0aGUgdGlzc3VlcyBhcHBlYXIgdG8gYmUgY2F0ZWdvcmlzZWQgaW4gYSBzb21ld2hhdCBzaW1pbGFyIHdheSBpbiBib3RoIGNsdXN0ZXJpbmcgYWxnb3JpdGhtcy4gSW4gYSBnZW5lcmFsIG92ZXJ2aWV3LCBpdCBhcHBlYXJzIHRoYXQgZGF0YSBpcyBhZ2dyZWdhdGVkIGFyb3VuZCB0aGVpciByZXNwZWN0aXZlIGFuYWx5c2VkIGNvbmRpdGlvbnMuIEFwYXJ0IGZyb20gYSBmZXcgZGlzY3JlcGFuY2llcywgZGlzdGFuY2UgZGF0YSBwb2ludHMgdG93YXJkcyBhIHNpbWlsYXJpdHkgcmVsYXRpb25zaGlwIGJldHdlZW4gbm9ybWFsIGNvcm5lYXMgdmVyc3VzIGRpc2Vhc2VkIG9uZXMsIGFuZCB0aGUgc2FtZSBhcHBsaWVzIHRvIEFxdWVvdXMgSHVtb3IuIEFsc28sIGl0IGlzIGNsZWFyIHRoYXQgZGlzZWFzZWQgY29ybmVhcyBhbmQgQXF1ZW91cyBIdW1vciBwcmVzZW50IHRoZW1zZWx2ZXMgdG8gYmUgdGhlIG1vc3QgZGlzdGFudCBmcm9tIGVhY2ggb3RoZXIuIEEgcGxhdXNpYmxlIGludGVycHJldGF0aW9uIG9mIHRoZXNlIGZhY3RvcnMgY2FuIGJlIHRoYXQgdGhlIGNsZWFyIHByb3hpbWl0eSBvZiBkYXRhIGZyb20gbm9ybWFsIGNvcm5lYXMgYW5kIGNvbnNlcXVlbnQgZGlzdGFuY2UgYmV0d2VlbiB0aGUgZGlzZWFzZWQgb25lcywgYW5kIHRoZSBmYWN0IHRoYXQgdGhlIHNhbWUgaXMgYXBwbGllZCBmb3IgQUggaW4gYm90aCBjYXNlcywgc3VnZ2VzdCBhIGRpZmZlcmVuY2UgaW4gZXhwcmVzc2lvbiBsZXZlbHMgb24gdGhlc2UgdGlzc3VlcywgYW5kIHRoZWlyIHJlc3BlY3RpdmVseSBzdGF0ZSwgYmVpbmcgYW5vdGhlciBldmlkZW5jZSBzdXBwb3J0aW5nIHRoZSBoeXBvdGhlc2lzIHRoYXQgQUggZGVmZmljaWVudGx5IHN1cHBsaWVzIGNvcm5lYXMgd2hlbiBhZmZlY3RlZCB3aXRoIEtDLiAKCllldCBhbm90aGVyIGZhY3RvciB0byBjb25zaWRlciB3b3VsZCBiZSB0aGUgYWxpdmUvZGVjZWFzZWQgc3RhdGUsIGZvciB0aGlzIGFnZ3JlZ2F0aW9uLCBhbHRob3VnaCBzdWdnZXN0aW5nIHJlc3VsdHMgY2xvc2VyIHRvIHRoZSBvbmVzIGV4cGVjdGVkLCB0aGV5IGRvbid0IHRha2UgaW4gY29uc2lkZXJhdGlvbiB0aGUgcG9zdC1tb3J0ZW0gcHJvY2Vzc2VzIG9uIHRoZSBtZXRhYm9saXRlcyBvZiB0aGVzZSB0aXNzdWVzLiAKCgojIE1hY2hpbmUgTGVhcm5pbmcKCiMjIFRyYWluaW5nIG1vZGVscyB3aXRoIGFsbCBkYXRhc2V0cyB1c2luZyBhcyBmaW5hbCBsYWJlbCB0aGUgIkRpc2Vhc2UiCgpgYGB7ciBEaXNlYXNlIGRhdGEgVHJhaW5pbmcsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRyYWluX3BlcmZvcm1hbmNlX2Rpc2Vhc2U8LXRyYWluX21vZGVsc19wZXJmb3JtYW5jZShNVEJMUzQ0NF9TY2FsZWQsIGMoInJmIiwiY3RyZWUiLCJuYWl2ZV9iYXllcyIsIm5iIiwicGxzIiksICJEaXNlYXNlIiwgImxvb2N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBudW0uZm9sZHMgPSA1LCBudW0ucmVwZWF0cyA9IDEwLCB0dW5lbGVuZ3RoID0gMTAsIAogICAgICAgICAgICAgICAgICAgICAgICAgdHVuZWdyaWQgPSBOVUxMLCBtZXRyaWMgPSBOVUxMLCBjb21wdXRlLnZhcmltcCA9IFQpCmBgYApUaGUgbnVtYmVyIG9mIHNhbXBsZXMgd2FzIHJlbGF0aXZlbHkgbG93LiBGb3IgdGhpcyByZWFzb24sIHRoZSBwcmVkaWN0aW9uIG1hZGUgYnkgdGhlIG1vZGVsIGlzIG5vdCBleHBlY3RlZCB0byBiZSBhcyBhY2N1cmF0ZSBhcyBpdCBzaG91bGQgYmUuCgpgYGB7cn0KRFQ6OmRhdGF0YWJsZSh0cmFpbl9wZXJmb3JtYW5jZV9kaXNlYXNlJHBlcmZvcm1hbmNlKQpgYGAKVGhlIGJlc3QgbW9kZWwgcmVwcmVzZW50YXRpb24gd2FzIHRoZSByYW5kb20gZm9yZXN0LCBzaW5jZSB0aGUgYXNzb2NpYXRlZCBhY2N1cmFjeSB3YXMgOTUlICh0aGUgaGlnaGVyIHZhbHVlIHdpdGhpbiBhbGwgbW9kZWwgcmVwcmVzZW50YXRpb25zKS4KCmBgYHtyfQp0cmFpbl9wZXJmb3JtYW5jZV9kaXNlYXNlJGNvbmZ1c2lvbi5tYXRyaWNlcyRyZgpgYGAKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmZfc2VsZWN0aW9uX2Rpc2Vhc2U8LWZlYXR1cmVfc2VsZWN0aW9uKE1UQkxTNDQ0X1NjYWxlZCwgIkRpc2Vhc2UiLCBtZXRob2QgPSAicmZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9ucz1jYXJldDo6cmZGdW5jcywgdmFsaWRhdGlvbiA9ICJyZXBlYXRlZGN2IiwgcmVwZWF0cyA9IDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSAxMCwgc3Vic2V0cyA9IDJeKDI6NCkpCmBgYApgYGB7cn0KdG9wMjBfZGlzZWFzZTwtZl9zZWxlY3Rpb25fZGlzZWFzZSRvcHRWYXJpYWJsZXNbMToyMF0KYXMuZGF0YS5mcmFtZSh0b3AyMF9kaXNlYXNlKQpgYGAKClRoZSBtb3N0IHJlbGV2YW50IGZlYXR1cmVzIHN1Z2dlc3QgdGhhdCBzb21lIG1ldGFib2xpdGVzIG1pZ2h0IGJlIGltcG9ydGFudCBtYXJrZXJzIHdoZW4gaXQgY29tZXMgdG8gcHJlZGljdCB3aGV0aGVyIGEgc3BlY2lmaWMgbWV0YWJvbGljIHByb2ZpbGUgY29ycmVzcG9uZHMgdG8gcG9zdC1tb3J0ZW0gY29uZGl0aW9ucyAod2l0aG91dCB0aGUgZGlzZWFzZSkgb3IgdG8gaHVtYW5zIHdpdGggdGhlIGRpc2Vhc2UuIFRoZSBtZXRhYm9saXRlcyBpZGVudGlmaWVkIHdlcmU6IEFjZXRhdGUgKDEuOSBwcG0pLCBNZXRoaW9uaW5lICgyLjEyIHBwbSksIENob2xpbmUgKDMuMTggcHBtKSwgQ2l0cmF0ZSAoMi42NCBwcG0pIGFuZCBUYXVyaW5lICgzLjIzIHBwbSkuCgoKIyMgVHJhaW5pbmcgbW9kZWxzIHdpdGggcGFydCBvZiB0aGUgZGF0YXNldCB3aXRoIGZpbmFsIGxhYmVsICJEaXNlYXNlIgpgYGB7ciBTcGxpdCBEYXRhc2V0IE1vZGVsIFRyYWluaW5nIHdpdGggRGlzZWFzZSBhcyBsYWJlbH0KaW5kaWNlcz1zYW1wbGUoMixuY29sKE1UQkxTNDQ0X1NjYWxlZCRkYXRhKSwgcmVwbGFjZT1ULCBwcm9iPWMoMC44LDAuMikpCmRhdGFUcj1NVEJMUzQ0NF9TY2FsZWQkZGF0YVssaW5kaWNlcz09MV0KZGF0YVRzdD1NVEJMUzQ0NF9TY2FsZWQkZGF0YVssaW5kaWNlcz09Ml0KZGF0YVRyPXN1YnNldF9zYW1wbGVzKE1UQkxTNDQ0X1NjYWxlZCwgY29sbmFtZXMoZGF0YVRyKSkKZGF0YVRzdD1zdWJzZXRfc2FtcGxlcyhNVEJMUzQ0NF9TY2FsZWQsIGNvbG5hbWVzKGRhdGFUc3QpKQpgYGAKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRyYWluX3BlcmZvcm1hbmNlX2Rpc2Vhc2Vfc3Vic2V0PC10cmFpbl9tb2RlbHNfcGVyZm9ybWFuY2UoZGF0YVRyLCBjKCJyZiIsImN0cmVlIiwibmFpdmVfYmF5ZXMiLCJuYiIsInBscyIpLCAiRGlzZWFzZSIsICJsb29jdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bS5mb2xkcyA9IDUsIG51bS5yZXBlYXRzID0gMTAsIHR1bmVsZW5ndGggPSAxMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVuZWdyaWQgPSBOVUxMLCBtZXRyaWMgPSBOVUxMLCBjb21wdXRlLnZhcmltcCA9IFQpCmBgYApgYGB7cn0KRFQ6OmRhdGF0YWJsZSh0cmFpbl9wZXJmb3JtYW5jZV9kaXNlYXNlX3N1YnNldCRwZXJmb3JtYW5jZSkKCmBgYAoKVGhlIGJlc3QgbW9kZWwgcmVwcmVzZW50YXRpb24gd2FzIHRoZSByYW5kb20gZm9yZXN0LCBzaW5jZSB0aGUgYXNzb2NpYXRlZCBhY2N1cmFjeSB3YXMgOTQlICh0aGUgaGlnaGVyIHZhbHVlIHdpdGhpbiBhbGwgbW9kZWwgcmVwcmVzZW50YXRpb25zKS4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByZWRpY3RlZF92YWx1ZXNfZGlzZWFzZV9zdWJzZXQ8LXByZWRpY3Rfc2FtcGxlcyh0cmFpbl9wZXJmb3JtYW5jZV9kaXNlYXNlX3N1YnNldCRmaW5hbC5tb2RlbHMkcmYsIGRhdGFUc3QkZGF0YSkKYGBgCmBgYHtyfQp0YWJsZShwcmVkaWN0ZWRfdmFsdWVzX2Rpc2Vhc2Vfc3Vic2V0JHByZWRpY3RlZC5jbGFzcywgZGF0YVRzdCRtZXRhZGF0YSREaXNlYXNlKQpgYGAKCiMjIFRyYWluaW5nIG1vZGVscyB3aXRoIGFsbCBkYXRhc2V0LCB1c2luZyBhcyBmaW5hbCBsYWJlbCB0aGUgdHlwZSBvZiB0aXNzdWUKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRyYWluX3BlcmZvcm1hbmNlX3Rpc3N1ZTwtdHJhaW5fbW9kZWxzX3BlcmZvcm1hbmNlKE1UQkxTNDQ0X1NjYWxlZCwgYygicmYiLCJjdHJlZSIsIm5haXZlX2JheWVzIiwibmIiLCJwbHMiKSwgIlRpc3N1ZSIsICJsb29jdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtLmZvbGRzID0gNSwgbnVtLnJlcGVhdHMgPSAxMCwgdHVuZWxlbmd0aCA9IDEwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1bmVncmlkID0gTlVMTCwgbWV0cmljID0gTlVMTCwgY29tcHV0ZS52YXJpbXAgPSBUKQpgYGAKYGBge3J9CkRUOjpkYXRhdGFibGUodHJhaW5fcGVyZm9ybWFuY2VfdGlzc3VlJHBlcmZvcm1hbmNlKQpgYGAKClRoZSBtb2RlbCByZXByZXNlbnRhdGlvbiB3aXRoIHRoZSBoaWdoZXN0IGFjY3VyYWN5IHdhcyBuYWl2ZV9iYXllcy4KCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHJhaW5fcGVyZm9ybWFuY2VfdGlzc3VlJGNvbmZ1c2lvbi5tYXRyaWNlcyRuYWl2ZV9iYXllcwoKZl9zZWxlY3Rpb25fdGlzc3VlPC1mZWF0dXJlX3NlbGVjdGlvbihNVEJMUzQ0NF9TY2FsZWQsICJUaXNzdWUiLCBtZXRob2QgPSAicmZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9ucz1jYXJldDo6cmZGdW5jcywgdmFsaWRhdGlvbiA9ICJyZXBlYXRlZGN2IiwgcmVwZWF0cyA9IDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSAxMCwgc3Vic2V0cyA9IDJeKDI6NCkpCmBgYApgYGB7cn0KdG9wMjBfdGlzc3VlPC1mX3NlbGVjdGlvbl90aXNzdWUkb3B0VmFyaWFibGVzWzE6MjBdCmFzLmRhdGEuZnJhbWUodG9wMjBfdGlzc3VlKQpgYGAKClRoZSBtb3N0IHJlbGV2YW50IGZlYXR1cmVzIHdlcmUgY2hlbWljYWwgc2hpZnRzIHJlbGF0ZWQgdG8gdGhlIGZvbGxvd2luZyBtZXRhYm9saXRlczogR2x5Y2luZSAoMy41MSBwcG0pLCBWYWxpbmUgKDEuMDIgcHBtKSwgTGFjdGF0ZSAoNC4xIHBwbSksIENob2xpbmUgKDMuMTggcG1tKSwgVGF1cmluZSAoMy4zNiBwcG0pLCBhbW9uZyBvdGhlcnMuCgpTaW5jZSB0aGUgZXhwZXJpbWVudGFsIGRhdGEgd2FzIG9idGFpbmVkIHVzaW5nIDFILU5NUiA3MDAgTUh6IGF0IDI1wrpDLCBhbmQgU3BlY21pbmUgZG9lcyBub3QgaGF2ZSBzcGVjaWZpYyBsaWJyYXJpZXMgZm9yIGlkZW50aWZpY2F0aW9uIG9mIDcwMCBNSHogTk1SLCB0aGUgaWRlbnRpZmljYXRpb24gb2YgdGhpcyBtZXRhYm9saXRlcyB3ZXJlIHBlcmZvcm1lZCByZXNvcnRpbmcgdG8gZmlnLiAxLgoKIVtSZXByZXNlbnRhdGlvbiBvZiAxSC1OTVIgcmVzdWx0cyB0YWtlbiBmcm9tIFNueXRrb3ZhIGV0IGFsLiAoMjAxNykuXShOTVJfQW5hbHlzaXMucG5nKQoKCgojIyBUcmFpbmluZyBtb2RlbHMgd2l0aCBwYXJ0IG9mIHRoZSBkYXRhc2V0LCB1c2luZyBhcyBmaW5hbCBsYWJlbCB0aGUgdHlwZSBvZiB0aXNzdWUKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0cmFpbl9wZXJmb3JtYW5jZV90aXNzdWVfc3Vic2V0PC10cmFpbl9tb2RlbHNfcGVyZm9ybWFuY2UoZGF0YVRyLCBjKCJyZiIsImN0cmVlIiwibmFpdmVfYmF5ZXMiLCJuYiIsInBscyIpLCAiVGlzc3VlIiwgImxvb2N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW0uZm9sZHMgPSA1LCBudW0ucmVwZWF0cyA9IDEwLCB0dW5lbGVuZ3RoID0gMTAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVuZWdyaWQgPSBOVUxMLCBtZXRyaWMgPSBOVUxMLCBjb21wdXRlLnZhcmltcCA9IFQpCmBgYApgYGB7cn0KRFQ6OmRhdGF0YWJsZSh0cmFpbl9wZXJmb3JtYW5jZV90aXNzdWVfc3Vic2V0JHBlcmZvcm1hbmNlKQpgYGAKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByZWRpY3RlZF92YWx1ZXNfdGlzc3VlX3N1YnNldDwtcHJlZGljdF9zYW1wbGVzKHRyYWluX3BlcmZvcm1hbmNlX3Rpc3N1ZV9zdWJzZXQkZmluYWwubW9kZWxzJG5haXZlX2JheWVzLCBkYXRhVHN0JGRhdGEpCmBgYApgYGB7cn0KdGFibGUocHJlZGljdGVkX3ZhbHVlc190aXNzdWVfc3Vic2V0JHByZWRpY3RlZC5jbGFzcywgZGF0YVRzdCRtZXRhZGF0YSRUaXNzdWUpCmBgYAoKSXQgd2FzIHBlcmZvcm1lZCBhIHRyYWluIG9mIHRoZSBtb2RlbCB3aXRoIGRpZmZlcmVudCB0eXBlcyBvZiBtb2RlbCByZXByZXNlbnRhdGlvbiBpbiBvcmRlciB0byBmaWd1cmUgb3V0IHdoaWNoIG9uZSB3YXMgdGhlIGJlc3QgZm9yIHRoZSBjb25zdHJ1Y3Rpb24gb2YgYSBtb2RlbCB0byBwcmVkaWN0IHdoZXRoZXIgdGhlIHNhbXBsZSBjb3JyZXNwb25kcyB0byBBSCwgY29ybmVhLCBkaXNlYXNlIG9yIGl0cyBhYnNlbmNlLgpUaGUgZmluYWwgbGFiZWwgaXMgdGhlIHByZXNlbmNlIG9mIGRpc2Vhc2Ugb3IgaXRzIGFic2VuY2UsIG9yIGlmIGl0IGJlbG9uZ3MgdG8gQUggb3IgY29ybmVhIHNhbXBsZS4gVGhlIHZhbGlkYXRpb24gbWV0aG9kIGNvbnNpZGVyZWQgd2FzIHRoZSBsZWF2ZS1vbmUtb3V0LiBBZnRlcndhcmRzLCBhIGZlYXR1cmUgc2VsZWN0aW9uIHdhcyBjb25kdWN0ZWQgdG8gZmlsdGVyIHRoZSBjaGVtaWNhbCBzaGlmdHMgd2hpY2ggd2VyZSBtb3JlIHJlbGV2YW50IGZvciB0aGUgcHJlZGljdGlvbi4KCkFzIGZvciB0aGUgZmlyc3QgMjAgbW9zdCBpbXBvcnRhbnQgZmVhdHVyZXMgc2VsZWN0ZWQsIHNldmVyYWwgY2hlbWljYWwgc2hpZnRzIHdlcmUgcmVsYXRlZCB0byBpbXBvcnRhbnQgbWV0YWJvbGl0ZXMgYXNzb2NpYXRlZCB0byBwb3N0IG1vcnRlbSBjb25kaXRpb25zIGFuZCBveGlkYXRpdmUgc3RyZXNzIGNhdXNlZCBieSB0aGUgZGlzZWFzZSBpbiBjb3JuZWEgdGlzc3Vlcy4KCkZvciBpbnN0YW5jZSwgYWNldGF0ZSAoMS45IHBwbSkgYW5kIGNpdHJhdGUgKDIuNjQgcHBtKSBzaG93biB0byBiZSBoaWdoZXIgaW4gY29ybmVhcyBvZiBLQyBwYXRpZW50cywgc3VnZ2VzdGluZyB0aGF0IG94aWRhdGl2ZSBzdHJlc3MgbWlnaHQgYmUgcmVsYXRlZCB0byBoaWdoZXIgY29uY2VudHJhdGlvbnMgb2YgdGhlIGFmb3JlbWVudGlvbmVkIGNvbXBvdW5kcy4gTW9yZW92ZXIsIHBvc3QtbW9ydGVtIGNvbmRpdGlvbnMgc3VjaCBhcyB0aGUgbGFjayBvZiBveHlnZW4gY2F1c2VzIHRoZSBpbmNyZWFzZSBpbiBjb25jZW50cmF0aW9uIGxldmVscyBvZiBsYWN0YXRlICg0LjEgcHBtKSBpbiBBSC4gKERvbmFsZHNvbiBhbmQgTGFtb3VudCAyMDEzLCAyMDE1OyBaZWxlbnRzb3ZhIGV0LmFsIDIwMTYpIAoKT3RoZXIgcG9zdC1tb3J0ZW0gY29uZGl0aW9ucywgaW4gcGFydGljdWxhciB0aGUgbGFjayBvZiBlbmVyZ3kgYWx0ZXJzIGltcG9ydGFudCBjZWxsIG1lY2hhbmlzbXMgc3VjaCBhcyBOYSsgLSBLKyB3YXRlciBwdW1wcywgaW5jcmVhc2Ugb3Ntb3RpYyBwcmVzc3VyZSwgbGVha2FnZSBvZiBtZXRhYm9saXRlcywgZXRjLiBUaGVzZSBwaGVub21lbmEgbGVhZCB0byBhIHNpZ25pZmljYW50IGluY3JlYXNlIG9mIHBvc3QtbW9ydGVtIGJpb21hcmtlcnMgY29uY2VudHJhdGlvbiBpbiBBSC4gVGhlc2UgYmlvbWFya2VycyBjb3VsZCBiZSBjaG9saW5lICgzLjE4IHBwbSksICB0YXVyaW5lICgzLjM2IHBwbSkgYW5kIGdseWNpbmUgKDMuNTEgcHBtKS4gKERvbmFsZHNvbiBhbmQgTGFtb3VudCAyMDEzLCAyMDE0LCAyMDE1OyBaZWxlbnRzb3ZhIGV0LmFsLiAyMDE2KS4gVGhlc2UgcmVwb3J0cyBjb3Jyb2JvcmF0ZSB0aGUgZmVhdHVyZSBzZWxlY3Rpb24gcmVzdWx0cywgc2luY2Ugc29tZSBvZiB0aGVtIHdlcmUgc2VsZWN0ZWQgYXMgcmVsZXZhbnQgZm9yIHRyYWluaW5nIG1vZGVscyBpbiBtYWNoaW5lIGxlYXJuaW5nLgoKIyBDb25jbHVzaW9uIAoKVGhlIHByZXNlbnQgd29yayBoYXMgZ2l2ZW4gdXMgc2V2ZXJhbCBpbnNpZ2h0cyBpbnRvIHRoZSBtZXRhYm9saWMgcHJvZmlsZXMgb2YgQ29ybmVhIGFuZCBBcXVlb3VzIEh1bW9yIGluIEtlcmF0b2NvbnVzIHBhdGllbnRzIGFuZCBwb3N0LW1vcnRlbSBzYW1wbGVzIChhYnNlbmNlIG9mIGRpc2Vhc2UpLgoKRXZlbiB0aG91Z2ggdGhlIGlkZW50aWZpY2F0aW9uIHByb2Nlc3Mgd2l0aCBzcGVjbWluZSBwYWNrYWdlIHdhcyBub3QgcmVsaWFibGUsIGl0IHdhcyBzdGlsbCBwb3NzaWJsZSB0byByb3VnaGx5IGlkZW50aWZ5IDIgbWV0YWJvbGl0ZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLgpUaGUgaWRlbnRpZmllZCBtZXRhYm9saXRlcyB3ZXJlIEdseWNpbmUgYW5kIERpaHlkcm91cmFjaWwuCgpHbHljaW5lIHdhcyBzdHJvbmdseSBjb3JyZWxhdGVkIHdpdGggUEMxIGluIHRoZSBQQyBBbmFseXNpcyB3aGljaCB3YXMgYWxzbyBjb3JyZWxhdGVkIHdpdGggcG9zdC1tb3J0ZW0gY29uZGl0aW9ucyAoTm9ybUtIIHNhbXBsZXMpLgpGdXRoZXJtb3JlLCBnbHljaW5lLXJlbGF0ZWQgcGF0aHdheSAoR2x1dGF0aGlvbmUgbWV0YWJvbGlzbSAtIGhzYTAwNDgwKSBhbmQgRGloeWRyb3VyYWNpbC1yZWxhdGVkIHBhdGh3YXkgKFB5cmltaWRpbmUgbWV0YWJvbGlzbSAtIGhzYTAwMjQwKSB3ZXJlIGxpa2VseSBhc3NvY2lhdGVkIHdpdGggcG9zdC1tb3J0ZW0gYmlvY2hlbWljYWwgcHJvY2Vzc2VzLiAKClRoZSBjbHVzdGVyaW5nIGFuYWx5c2lzIHNob3dlZCB0aGF0IHRoZSBzYW1wbGVzIGNhbiBiZSBlYXNpbHkgaWRlbnRpZmllZCBieSB0aGVpciB0aXNzdWUgYnV0IG5vdCBhcyBlYXNpbHkgcmVnYXJkaW5nIHRoZWlyIGRpc2Vhc2UgY29uZGl0aW9uLgoKSW4gb3JkZXIgdG8gZWZmZWN0aXZlbHkgdHJhaW4gdGhlIHByZWRpY3Rpb24gbW9kZWxzLCBhIGhpZ2hlciBudW1iZXIgb2Ygc2FtcGxlcyB3b3VsZCBiZSByZXF1aXJlZC4KVGhlIGZlYXR1cmUgc2VsZWN0aW9uIHJlc3VsdHMgc2hvdyB0aGF0IEFjZXRhdGUgKDEuOSBwcG0pIGFuZCBDaXRyYXRlICgyLjY1IHBwbSkgYXJlIHJlbGV2YW50IGZlYXR1cmVzIGZvciB0aGUgcHJlZGljdGlvbiBvZiBoZWFsdGggc3RhdHVzIChwcmVzZW5jZSBvciBhYnNlbmNlIG9mIEtDKS4KVGhlc2UgcmVzdWx0cyBhcmUgY29tcGxpYW50IHdpdGggdGhlIHJlcG9ydGVkIHJlc3VsdHMgaW4gbGl0ZXJhdHVyZSwgZ2l2ZW4gdGhlc2UgY29tcG91bmRzIGFyZSByZXBvcnRlZCBhcyBiZWluZyByZWxhdGVkIHRvIG94aWRhdGl2ZSBzdHJlc3MgaW4gY29ybmVhcyAoQnVkZGkgZXQgYWwuIDIwMDI7IEFybmFsIGV0IGFsLiAyMDExOyBXb2pjaWsgZXQgYWwuIDIwMTMsIDIwMTQ7IEthcmFtaWNob3MgZXQgYWwuIDIwMTQ7IFNob2hhbSBldCBhbC4gMjAwOCkuCkFkZGl0aW9uYWxseSwgb3RoZXIgbWV0YWJvbGl0ZXMgd2VyZSBjb25zaWRlcmVkIGFzIHJlbGV2YW50IGZlYXR1cmVzIGZvciB0aGUgcHJlZGljdGlvbiBvZiB0aXNzdWUgdHlwZS4KQXMgcmVwb3J0ZWQgaW4gbGl0ZXJhdHVyZSwgdGhlc2UgbWV0YWJvbGl0ZXMgKExhY3RhdGUsIEdseWNpbmUsIENob2xpbmUsIFRhdXJpbmUsIGV0YykgYXJlIGJpb21hcmtlcnMgZm9yIHRoZSBlc3RpbWF0aW9uIG9mIHBvc3QtbW9ydGVtIGludGVydmFsIGFuZCB0ZW5kIHRvIGFjY3VtdWxhdGUgaW4gQXF1ZW91cyBIdW1vciBkdWUgdG8gcG9zdC1tb3J0ZW0gYmlvY2hlbWljYWwgcHJvY2Vzc2VzIChEb25hbGRzb24gYW5kIExhbW91bnQgMjAxMywgMjAxNCwgMjAxNTsgWmVsZW50c292YSBldCBhbC4gMjAxNikuClRodXMsIHRoZXNlIGZlYXR1cmVzIHNlZW0gdG8gYmUgaW4gbGluZSB3aXRoIHByZXZpb3VzIHJlcG9ydHMsIHRoZXJlZm9yZSB0aGV5IHNlZW0gdG8gYmUgZ29vZCB0byB0cmFpbiBtb2RlbHMgcmVnYXJkaW5nIHRoZSB0eXBlIG9mIHRpc3N1ZSBhbmQgaGVhbHRoIHN0YXR1cy4KCg==